<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Andre Claudinei Barsotti</title>
    <description>The latest articles on Forem by Andre Claudinei Barsotti (@andrebarsotti).</description>
    <link>https://forem.com/andrebarsotti</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F703793%2F21b7536d-4663-48bb-9946-08f0ff777ec1.jpg</url>
      <title>Forem: Andre Claudinei Barsotti</title>
      <link>https://forem.com/andrebarsotti</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/andrebarsotti"/>
    <language>en</language>
    <item>
      <title>Reconhecimento de Voz no Android: Utilizando a lib android.speech</title>
      <dc:creator>Andre Claudinei Barsotti</dc:creator>
      <pubDate>Sun, 21 Jan 2024 20:32:38 +0000</pubDate>
      <link>https://forem.com/andrebarsotti/reconhecimento-de-voz-no-android-utilizando-a-lib-androidspeech-1ahn</link>
      <guid>https://forem.com/andrebarsotti/reconhecimento-de-voz-no-android-utilizando-a-lib-androidspeech-1ahn</guid>
      <description>&lt;p&gt;O processamento de língua falada, como tantos outros, é um capitulo interessante do Processamento de Linguagem Natural (PLN) e esta vinculado ao subcampo da &lt;em&gt;Natural Languge Understand&lt;/em&gt; (NLU). Nesse processo busca-se basicamente fazer com que o dispositivo (computador, celular, etc.) seja capaz de "ouvir" e então transcrever o que foi falado em texto.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“O processamento da língua falada depende de uma vasta gama de conhecimentos que inclui acústica, fonologia, fonética, linguística geral, semântica, sintaxe, pragmática, estruturas discursivas, entre outras. Para além disso, outros conhecimentos mais comuns à ciência da computação, à engenharia elétrica, à matemática e, até mesmo à psicologia, também são necessários” (Caseli &lt;em&gt;et al.&lt;/em&gt;, 2023, p. 15)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftx4zed1lkcl5ihcf4rlq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftx4zed1lkcl5ihcf4rlq.png" alt="Fig. 1: Esquema de reconhecimento de voz. Fonte: Caseli *et al.*, 2023, p. 27"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Atualmente existem diversas bibliotecas que já nos fornecem a parte básica desse processo, sendo conhecidos como ASR Convencionais. Neles o resultado trata-se apenas de uma sequência de palavras, sem pontuações ou validações gramaticais, e que podem ser utilizados como base para outras aplicações.&lt;/p&gt;

&lt;p&gt;Nesse artigo vamos explorar aspectos da implementação da biblioteca &lt;em&gt;android.speech&lt;/em&gt;, nativa nos dispositivos Android e que trata-se exatamente de uma dessas ASR Convencionais. Não é nosso objetivo servir como tutorial, para essa finalidade sugerimos os artigos, em inglês, de &lt;a href="https://medium.com/@daniel.atitienei/voice-to-text-in-jetpack-compose-android-c1e077627abe" rel="noopener noreferrer"&gt;Atitienei&lt;/a&gt; e &lt;a href="https://medium.com/geekculture/add-voice-commands-to-android-apps-80157c0d5bcc" rel="noopener noreferrer"&gt;Khare&lt;/a&gt; onde um passo-a-passo foi dado e que aplicamos em nosso aplicativo de exemplos que esta no &lt;a href="https://github.com/andrebarsotti/lab-voice-to-text-android" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bibliotecas e permissões
&lt;/h2&gt;

&lt;p&gt;Para incluir o STT (&lt;em&gt;speech-to-text&lt;/em&gt;) em uma aplicação Android nenhuma biblioteca externa é necessária, porém é preciso que a aplicação tenha permissões para "gravar" audios. Dessa forma é preciso incluir a linha abaixo no manifesto da aplicação:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;uses-permission&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.permission.RECORD_AUDIO"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De forma complementar também será necessário solicitar a permissão de audio em algum momento o que pode ser feito da seguinte forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;ActivityCompat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;requestPermissions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;Activity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;arrayOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Manifest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;permission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;RECORD_AUDIO&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="mi"&gt;123&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reconhecendo a fala do usuário e convertendo em texto
&lt;/h2&gt;

&lt;p&gt;Existem dois elementos básicos necessários para utilizar a função de texto para fala da biblioteca nativa do android:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SpeechRecognizer&lt;/strong&gt;: Essa é a classe responsável por efetivamente executar a função de reconhecimento de voz.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RecognitionListener&lt;/strong&gt;: Essa é uma interface onde os retornos das chamadas do reconhecimento de voz podem ser manipulados através de sua implementação em um objeto concreto.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O início do processo acontece quando uma instância do &lt;em&gt;SpeechRecognizer&lt;/em&gt; é criada a partir do método estático &lt;em&gt;factory&lt;/em&gt; da própria classe como no exemplo abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.speech.SpeechRecognizer&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;recognizer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SpeechRecognizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createSpeechRecognizer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse caso o contexto pode ser tanto a aplicação quanto a &lt;em&gt;Activity&lt;/em&gt;, no nosso app de exemplo utilizamos como contexto a própria aplicação.&lt;/p&gt;

&lt;p&gt;Com o &lt;em&gt;recognizer&lt;/em&gt; criado vamos agora setar o &lt;em&gt;listener&lt;/em&gt;, que será responsável por intermediar o que será reconhecido e tratar o texto resultante. Para setar utilize o método &lt;em&gt;setRecognitionListener&lt;/em&gt; como no exemplo abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;recognizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setRecognitionListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora será preciso definir uma &lt;em&gt;Intent&lt;/em&gt; que irá iniciar nossa aplicação, esse intent passa para o &lt;em&gt;SpeechRecognizer&lt;/em&gt; vários parâmetros que desejamos. Abaixo um exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.speech.RecognizerIntent&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;intent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Intent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RecognizerIntent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ACTION_RECOGNIZE_SPEECH&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;putExtra&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;RecognizerIntent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;EXTRA_LANGUAGE_MODEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;RecognizerIntent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LANGUAGE_MODEL_FREE_FORM&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;putExtra&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RecognizerIntent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;EXTRA_PARTIAL_RESULTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;putExtra&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RecognizerIntent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;EXTRA_LANGUAGE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"pt-BR"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nessa &lt;em&gt;Intent&lt;/em&gt; informamos que nossa ação será de reconhecimento de voz (ACTION_RECOGNIZE_SPEECH), o extra EXTRA_LANGUAGE_MODEL é obrigatório pois precisamos definir o modelo de reconhecimento de falar que será utilizado, no nosso caso utilizamos o LANGUAGE_MODEL_FREE_FORM que indica um modelo de fala livre. Já o extra EXTRA_PARTIAL_RESULTS setado como &lt;em&gt;true&lt;/em&gt; nos permite receber parciais do texto durante o reconhecimento da fala e o EXTRA_LANGUAGE com o valor &lt;em&gt;pt-BR&lt;/em&gt; garante que haverá reconhecimento de voz para o português brasileiro. Mais detalhes sobre os parâmetros pode ser obtido na &lt;a href="https://developer.android.com/reference/android/speech/RecognizerIntent#ACTION_RECOGNIZE_SPEECH" rel="noopener noreferrer"&gt;documentação do Intent&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Com esses passos feitos podemos iniciar o reconhecimento de voz chamando o método &lt;em&gt;startListening&lt;/em&gt; passando nossa &lt;em&gt;Intent&lt;/em&gt; como parâmetro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;recognizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startListening&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para interromper basta chamar o método &lt;em&gt;stopListening&lt;/em&gt;. Abaixo o exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;recognizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stopListening&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como mencionado anteriormente os texto gerado pelo &lt;em&gt;SpeechRecognizer&lt;/em&gt; é tratado em uma instância concreta da interface &lt;em&gt;RecognitionListener&lt;/em&gt;, pois é nela que estão os eventos. Essa interface obriga a implementação dos seguintes métodos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;onReadyForSpeech&lt;/strong&gt;: É chamado quando o &lt;em&gt;SpeechRecognizer&lt;/em&gt; foi corretamente inicializado e esta pronto para processar a voz do usuário. Pode ser utilizado para indicar na interface com o usuário que ele pode começar a falar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;onBeginningOfSpeech&lt;/strong&gt;: É chamado após o &lt;em&gt;SpeechRecognizer&lt;/em&gt; identificar que o usuário começou a falar. Essa informação pode ser utilizada para indicar graficamente na interface que o usuário começou a falar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;onRmsChanged&lt;/strong&gt;: Esse método recebe como um &lt;em&gt;float&lt;/em&gt; (rmsdB) que indica uma métrica da variação do volume da fala durante o reconhecimento da voz. Pode ser utilizado para indicar graficamente na interface que a voz esta sendo reconhecida.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;onEndOfSpeech&lt;/strong&gt;: É chamado após o &lt;em&gt;SpeechRecognizer&lt;/em&gt; identificar que o usuário terminou de falar. Essa informação pode ser utilizada para indicar graficamente na interface que o usuário terminou a falar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;onResults&lt;/strong&gt; e &lt;strong&gt;onPartialResults&lt;/strong&gt;: recebe um &lt;em&gt;Bundle&lt;/em&gt; como parâmetro com o resultado do processamento total (&lt;em&gt;onResults&lt;/em&gt;) ou parcial (&lt;em&gt;onPartialResults&lt;/em&gt;), antes do usuário terminar de falar. É através desses métodos que o texto do que foi falados é gerado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;onError&lt;/strong&gt;: Quando acontece algum erro no processamento da fala (fala irreconhecida, por exemplo) esse método será chamado e ele recebe um inteiro com o código do erro correspondente.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;onBufferReceived&lt;/strong&gt;: Recebe um &lt;em&gt;buffer&lt;/em&gt; como um array de &lt;em&gt;bytes&lt;/em&gt; que pode ser utilizado para salvar o audio gravado se for desejado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;onEvent&lt;/strong&gt;: Esse método esta reservado para uso futuro e no momento &lt;em&gt;não&lt;/em&gt; é chamado.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mais detalhes sobre cada um dos &lt;em&gt;callbacks&lt;/em&gt; pode ser encontrada na &lt;a href="https://developer.android.com/reference/android/speech/RecognitionListener" rel="noopener noreferrer"&gt;documentação&lt;/a&gt;. Podemos verificar que os métodos mais relevantes são o &lt;em&gt;onResults&lt;/em&gt; e o &lt;em&gt;onError&lt;/em&gt;, pois contemplam o texto transcrito do que foi falado ou o erro, caso aconteça algum problema. Abaixo um exemplo de implementação simples.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.speech.RecognitionListener&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.widget.Toast&lt;/span&gt;

&lt;span class="n"&gt;recognizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setRecognitionListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nc"&gt;RecognitionListener&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onReadyForSpeech&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bundle&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onBeginningOfSpeech&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onRmsChanged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rmsdB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onBufferReceived&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ByteArray&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onEndOfSpeech&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;msgError&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;SpeechRecognizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ERROR_NETWORK_TIMEOUT&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Network timeout"&lt;/span&gt;
            &lt;span class="nc"&gt;SpeechRecognizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ERROR_NETWORK&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Network error"&lt;/span&gt;
            &lt;span class="nc"&gt;SpeechRecognizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ERROR_AUDIO&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Audio recording error"&lt;/span&gt;
            &lt;span class="nc"&gt;SpeechRecognizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ERROR_SERVER&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Server error"&lt;/span&gt;
            &lt;span class="nc"&gt;SpeechRecognizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ERROR_SPEECH_TIMEOUT&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Speech input"&lt;/span&gt;
            &lt;span class="nc"&gt;SpeechRecognizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ERROR_NO_MATCH&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"No recognition result matched."&lt;/span&gt;
            &lt;span class="nc"&gt;SpeechRecognizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ERROR_RECOGNIZER_BUSY&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"RecognitionService busy"&lt;/span&gt;
            &lt;span class="nc"&gt;SpeechRecognizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ERROR_INSUFFICIENT_PERMISSIONS&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Insufficient permissions"&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Didn't understand, please try again."&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nc"&gt;Toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"Error: $msgError"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LENGTH_SHORT&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bundle&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt;
            &lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;getStringArrayList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SpeechRecognizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;RESULTS_RECOGNITION&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;getOrNull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="nc"&gt;Toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"Text: $text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LENGTH_LONG&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onPartialResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;partialResults&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bundle&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eventType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bundle&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusões
&lt;/h2&gt;

&lt;p&gt;A implementação do ASR em aplicações Android Nativas com a biblioteca nativa &lt;em&gt;android.speech&lt;/em&gt; provou ser extremamente simplificada e prática, sem grandes complexidades no processo. Se o dispositivo estiver corretamente configurado em testes iniciais provou-se possível o seu uso &lt;em&gt;offline&lt;/em&gt;, entende-se que seja necessário solicitar que o pacote de reconhecimento de fala padrão do assistente de voz local seja baixado para esse tipo de uso.&lt;/p&gt;

&lt;p&gt;Tendo em vista sua facilidade e a ausência de pacotes adicionais entendem-se que trata-se de uma forma viável para o uso embarcado da tecnologia em aplicações Android Nativas.&lt;/p&gt;

&lt;p&gt;Por ser um modelo convencional pode ser necessário algum tratamento do seu resultado conforme o uso desejado para o texto. Supondo, por exemplo, que seja desejado utilizá-lo para transcrições talvez seja necessário treinar um modelo para predição de pontuação para então utilizá-lo em uma aplicação produtiva, um exemplo da arquitetura esta na figura abaixo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flqbh48dspw1i410doct4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flqbh48dspw1i410doct4.png" alt="Fig. 2: Modelo para processamento de voz. Fonte: Adaptado de Caseli *et al.*, 2023, p. 61"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Um exemplo de prático aplicação dos conceitos aqui descritos pode ser encontrado no &lt;a href="https://github.com/andrebarsotti/lab-voice-to-text-android" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; do autor. Esse aplicativo &lt;em&gt;não&lt;/em&gt; dispõe ainda da habilidade de prever pontuação porém pode ser um ótimo ponto de partida, ele foi construído tomando como base o passo-a-passo descrito por Atitienei (2023) em seu artigo do Medium.&lt;/p&gt;

&lt;h2&gt;
  
  
  REFERÊNCIAS
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;ANDROID API REFERENCE&lt;/strong&gt;: android.speech. [S. l.], [s. d.]. Disponível em: &lt;a href="https://developer.android.com/reference/android/speech/package-summary" rel="noopener noreferrer"&gt;https://developer.android.com/reference/android/speech/package-summary&lt;/a&gt;. Acesso em: 12 jan. 2024.&lt;/p&gt;

&lt;p&gt;ATITIENEI, D. &lt;strong&gt;Voice to Text in Jetpack Compose — Android&lt;/strong&gt;. &lt;em&gt;In&lt;/em&gt;: MEDIUM. 10 mar. 2023. Disponível em: &lt;a href="https://medium.com/@daniel.atitienei/voice-to-text-in-jetpack-compose-android-c1e077627abe" rel="noopener noreferrer"&gt;https://medium.com/@daniel.atitienei/voice-to-text-in-jetpack-compose-android-c1e077627abe&lt;/a&gt;. Acesso em: 9 jan. 2024.&lt;/p&gt;

&lt;p&gt;CASELI, H. M. (org.) &lt;em&gt;et al&lt;/em&gt;. &lt;strong&gt;Processamento de Linguagem Natural:&lt;/strong&gt; Conceitos, Técnicas e Aplicações em Português. 1. ed. &lt;em&gt;In:&lt;/em&gt; Brasileiras em Processamento de Linguagem Natural. São Carlos: BPLN, 2023. &lt;em&gt;E-Book&lt;/em&gt;. cap. 2 e cap.3 p. 15-63.  Disponível em: &lt;a href="https://brasileiraspln.com/livro-pln" rel="noopener noreferrer"&gt;https://brasileiraspln.com/livro-pln&lt;/a&gt;. Acesso em: 20 dez. 2023.&lt;/p&gt;

&lt;p&gt;KHARE, A. &lt;strong&gt;Add Voice Commands to Android Apps&lt;/strong&gt;. &lt;em&gt;In&lt;/em&gt;: MEDIUM. GEEK CULTURE. 6 jul. 2021. Disponível em: &lt;a href="https://medium.com/geekculture/add-voice-commands-to-android-apps-80157c0d5bcc" rel="noopener noreferrer"&gt;https://medium.com/geekculture/add-voice-commands-to-android-apps-80157c0d5bcc&lt;/a&gt;. Acesso em: 9 jan. 2024.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>nlp</category>
      <category>android</category>
      <category>kotlin</category>
    </item>
    <item>
      <title>Scripts em C#</title>
      <dc:creator>Andre Claudinei Barsotti</dc:creator>
      <pubDate>Tue, 14 Sep 2021 12:56:21 +0000</pubDate>
      <link>https://forem.com/andrebarsotti/scripts-em-c-10ff</link>
      <guid>https://forem.com/andrebarsotti/scripts-em-c-10ff</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Scripts são uma ferramenta bem antiga nos ambientes de TI e ainda hoje são muito utilizados. &lt;/p&gt;

&lt;p&gt;Sua natureza interpretada da à eles um dinamismo que supera em muito as facilidades de qualquer linguagem compilada.&lt;/p&gt;

&lt;p&gt;JavaScript, com Node Js, e Python são exemplos que demonstram que a utilização de scripts no desenvolvimento de aplicações ainda segue em alta e sua força.&lt;/p&gt;

&lt;p&gt;Estudando sobre Azure Functions me deparei com um arquivo a diferente extensão ".csx". Trata-se de um arquivo de scripts em linguagem C#, uma novidade para mim depois de vários anos trabalhando com essa linguagem.&lt;/p&gt;

&lt;p&gt;Compartilho aqui com vocês o que aprendi sobre essa ferramenta e minhas conclusões.&lt;/p&gt;

&lt;h2&gt;
  
  
  Os scripts em C Sharp
&lt;/h2&gt;

&lt;p&gt;Nos idos de 2011, Kirill Osenkov informou a comunidade .NET que a MS estava entregando o primeiro &lt;em&gt;release preview&lt;/em&gt; do Roslyn Project. Nesse artigo, ele também informa que foi "&lt;em&gt;introduzido o conceito de um arquivo de script C#&lt;/em&gt;" (OSENKOV, 2011). "&lt;em&gt;A ideia principal por trás de escrever scripts em C# foi permitir que o código fosse avaliado dinamicamente pelo _runtime&lt;/em&gt;." (WOJ, 2015).&lt;/p&gt;

&lt;p&gt;Para escrever um script C# você só precisa criar um arquivo com a extensão ".csx" em qualquer editor de textos. Depois de criar o arquivo você vai precisar de um programa para interpretá-lo. Hoje três opções:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Mono/Roslyn CSI&lt;/em&gt; (que já vem instalado com o Visual Studio);&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;cs-scripts&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;dotnet-scripts&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O &lt;em&gt;cs-scripts&lt;/em&gt; e &lt;em&gt;dotnet-scripts&lt;/em&gt; são multiplataforma, e  &lt;em&gt;dotnet-scripts&lt;/em&gt; tem a vantagem ser instalado com um &lt;code&gt;dotnet tool&lt;/code&gt; e rodar usando o .NET 5. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;No restante desse artigo vamos utilizar o dotnet-scripts para nossos exemplos. Para instalá-lo digite o comando abaixo em seu console de preferência:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet tool &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; dotnet-script
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sintaxe
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"Um script C# tem requisitos de sintaxe mais flexíveis, então a experiência geral pode ser sem cerimônias.  Abaixo estão algumas coisas a serem lembradas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;o ponto de entrada para o seu script é a primeira linha do seu arquivo (nenhum método &lt;code&gt;Main&lt;/code&gt; obrigatório)&lt;/li&gt;
&lt;li&gt;qualquer código é permitido a partir da primeira linha (nenhuma classe de nível superior, &lt;code&gt;Program&lt;/code&gt;, obrigatória)&lt;/li&gt;
&lt;li&gt;funções globais são permitidas;&lt;/li&gt;
&lt;li&gt;sem &lt;code&gt;namespaces&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;sem um arquivo de projeto ou solução;&lt;/li&gt;
&lt;li&gt;seu script pode ser totalmente autocontido;&lt;/li&gt;
&lt;li&gt;instruções &lt;code&gt;using&lt;/code&gt; e referências são importados implicitamente pelo aplicativo hospedeiro (responsável por executar o script)"
(WOJCIESZYN, 2015)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Eu acrescento à essa lista o desenvolvimento de extensões, que foi algo que identifiquei nos meus testes. &lt;/p&gt;

&lt;p&gt;Abaixo um exemplo de arquivo de script C# utilizado para inicializar o processo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt; &lt;span class="s"&gt;"Configs.csx"&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt; &lt;span class="s"&gt;"src/Data/TodoListRepository.csx"&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt; &lt;span class="s"&gt;"src/Services/TodoListService.csx"&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt; &lt;span class="s"&gt;"src/Controller/TodoListController.csx"&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Extensions.Configuration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToArray&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;TodoListRepository&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Configs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetConnectionString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"db"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;TodoListService&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;TodoListController&lt;/span&gt; &lt;span class="n"&gt;controller&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExecuteCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como pode ser visto a sintaxe da linguagem é a mesma já conhecida, só que sem a estrutura &lt;code&gt;Program.Main&lt;/code&gt;. A forma de referenciar outros arquivos ".csx" é utilizando a diretiva &lt;code&gt;#load "&amp;lt;caminho do arquivo&amp;gt;"&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Abaixo um exemplo de arquivo para leitura de configurações, que faz referência à pacotes nuget:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="s"&gt;"nuget: Microsoft.Extensions.Configuration, 5.0.0"&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="s"&gt;"nuget: Microsoft.Extensions.Configuration.Binder, 5.0.0"&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="s"&gt;"nuget: Microsoft.Extensions.Configuration.UserSecrets, 5.0.0"&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="s"&gt;"nuget: Microsoft.Extensions.Configuration.EnvironmentVariables, 5.0.0"&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Extensions.Configuration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Configs&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IConfiguration&lt;/span&gt; &lt;span class="n"&gt;_config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IConfiguration&lt;/span&gt; &lt;span class="n"&gt;Configuration&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;get&lt;/span&gt; 
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_config&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nf"&gt;SetConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;SetConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_config&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ConfigurationBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetBasePath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Directory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetCurrentDirectory&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddJsonFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"appsettings.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;optional&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reloadOnChange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddUserSecrets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"csx-script-app"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddEnvironmentVariables&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;GetConfig&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;sectionName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetSection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sectionName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Referenciar um pacote é bem simples utilizando &lt;code&gt;#r "nuget: &amp;lt;nome do pacote&amp;gt;, &amp;lt;versão&amp;gt;"&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Se for necessário importar um &lt;em&gt;assembly&lt;/em&gt; próprio é utilize a direntiva &lt;code&gt;#r "&amp;lt;caminho da dll&amp;gt;"&lt;/code&gt;. Segue um exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"./build/MeuAssembly.dll"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Desenvolvi um aplicativo &lt;em&gt;Todo&lt;/em&gt; de exemplo e publiquei no meu GitHub onde é possível ver esses scripts em ação. Esse é o &lt;a href="https://github.com/andrebarsotti/csx-script-sample"&gt;link&lt;/a&gt; do projeto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debug
&lt;/h2&gt;

&lt;p&gt;Se você utiliza o Visual Studio Code como seu editor de texto/IDE debugar um script é algo que seguirá os padrões que você já esta acostumado. Basta configurar seu &lt;em&gt;launch.json&lt;/em&gt; conforme abaixo, colocar o &lt;em&gt;breakpoint&lt;/em&gt; e clicar em F5.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"configurations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".NET Script Debug - Linux"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"coreclr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"program"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${env:HOME}/.dotnet/tools/dotnet-script"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"${file}"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"cwd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceFolder}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"stopAtEntry"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".NET Script Debug - Windows"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"coreclr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"program"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dotnet"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="s2"&gt;"${env:USERPROFILE}/.dotnet/tools/.store/dotnet-script/1.2.1/dotnet-script/1.2.1/tools/net5.0/any/dotnet-script.dll"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="s2"&gt;"${file}"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"cwd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceRoot}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"stopAtEntry"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Compilação com um aplicativo e execução no Linux.
&lt;/h2&gt;

&lt;p&gt;Um ponto interessante que achei utilizando o &lt;code&gt;dotnet-script&lt;/code&gt; no Windows foi a possibilidade de criar um aplicativo autocontido. Para fazer isso é muito simples basta publicar o script como no exemplo abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet script publish Main.csx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Um diretório &lt;em&gt;publish&lt;/em&gt; será criado com um executável. Como é um aplicativo autocontido, basta copiá-lo para qualquer computador e, mesmo sem o .NET instalado, executá-lo.&lt;/p&gt;

&lt;p&gt;Em um ambiente Linux incluindo como primeira linha a diretiva &lt;code&gt;#!/usr/bin/env dotnet-script&lt;/code&gt; é possível executar o script como qualquer outro, lembrando que é preciso dar permissão de execução no arquivo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão e aplicações
&lt;/h2&gt;

&lt;p&gt;Observando a tecnologia vemos que essa ferramenta é bem madura e que vem se desenvolvendo junto com a plataforma e que irá continuar nesse caminho no futuro.&lt;/p&gt;

&lt;p&gt;Hoje é possível escrever um programa console em C# de forma minimalista sem uma classe Program, um método Main e com funções globais, algo que até pouco tempo atrás era impensável. Com scripts C# você consegue tudo isso e ainda a vantagem de desenvolver sem um ".csproj" e sem o tempo de compilação, apenas escrever o código e já validar seu programa prontamente.&lt;/p&gt;

&lt;p&gt;Testes de integração que serão executados sob demanda; programas de carga que serão utilizados apenas uma vez; pequenos testes e estudos de algum pacote Nuget novo; Scripts de configuração de ambiente. Esses são apenas alguns exemplos de utilização de scripts em C#.&lt;/p&gt;

&lt;p&gt;No caso de scripts para configuração de ambiente ou inicialização de uma aplicativo, ainda existe a vantagem latente de seguir com a mesma linguagem que o projeto foi desenvolvido. Para a equipe isso é uma vantagem, visto que é preciso um esforço adicional para aprender e escrever o mesmo script com um bash script ou bat tradicional.&lt;/p&gt;

&lt;p&gt;Em programas de carga existe ainda a vantagem de conseguir reaproveitar o código e as regras de negócio do próprio projeto, sem duplicidades.&lt;/p&gt;

&lt;p&gt;As aplicações são muitas e certamente vale a pena incluir no "arsenal".&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;p&gt;BAHRAMINEZHAD, Ali. Hitchhiker’s Guide to the C# scripting. ITNEXT, 2019. Disponível em: &amp;lt;&lt;a href="https://itnext.io/hitchhikers-guide-to-the-c-scripting-13e45f753af9"&gt;https://itnext.io/hitchhikers-guide-to-the-c-scripting-13e45f753af9&lt;/a&gt;&amp;gt;. Acesso em: 11-09-2021&lt;/p&gt;

&lt;p&gt;MICHAELIS, Mark. C# Scripting. Microsotf Docs, 2016. Disponível em: &amp;lt;&lt;a href="https://docs.microsoft.com/en-us/archive/msdn-magazine/2016/january/essential-net-csharp-scripting"&gt;https://docs.microsoft.com/en-us/archive/msdn-magazine/2016/january/essential-net-csharp-scripting&lt;/a&gt;&amp;gt;. Acesso em: 11-09-2021&lt;/p&gt;

&lt;p&gt;OSENKOV, Kirill. Introducing the Microsoft “Roslyn” CTP. Microsoft DevBlogs, 2011. Disponível em &amp;lt;&lt;a href="https://devblogs.microsoft.com/visualstudio/introducing-the-microsoft-roslyn-ctp/"&gt;https://devblogs.microsoft.com/visualstudio/introducing-the-microsoft-roslyn-ctp/&lt;/a&gt;&amp;gt;. Acesso em: 12-09-2021&lt;/p&gt;

&lt;p&gt;SALVADEO, André C B. Todo List em C# script (CSX). Github, 2021. Disponível em &amp;lt;&lt;a href="https://github.com/andrebarsotti/csx-script-sample"&gt;https://github.com/andrebarsotti/csx-script-sample&lt;/a&gt;&amp;gt;. Acesso em: 12-09-2021&lt;/p&gt;

&lt;p&gt;VOGEL, Peter. Making Your Life Easier with C# Scripting. Visual Studio Magazine, 2021. Disponível em: &amp;lt;&lt;a href="https://visualstudiomagazine.com/articles/2021/06/14/csharp-scripting.aspx"&gt;https://visualstudiomagazine.com/articles/2021/06/14/csharp-scripting.aspx&lt;/a&gt;&amp;gt;. Acesso em: 11-09-2021&lt;/p&gt;

&lt;p&gt;WOJCIESZYN, Filip. Dotnet script. Github, 2021. Disponível em &amp;lt;&lt;a href="https://github.com/filipw/dotnet-script"&gt;https://github.com/filipw/dotnet-script&lt;/a&gt;&amp;gt;. Acesso em: 11-09-2021&lt;/p&gt;

&lt;p&gt;WOJCIESZYN, Filip. Adding C# scripting to your development arsenal - Part 1. Microsoft Docs - Blog Archive - Canadian Developer Connection, 2015. Disponível em &amp;lt;&lt;a href="https://docs.microsoft.com/pt-br/archive/blogs/cdndevs/adding-c-scripting-to-your-development-arsenal-part-1"&gt;https://docs.microsoft.com/pt-br/archive/blogs/cdndevs/adding-c-scripting-to-your-development-arsenal-part-1&lt;/a&gt;&amp;gt;. Acesso em: 12-09-2021&lt;/p&gt;

</description>
      <category>ptbr</category>
      <category>csharp</category>
      <category>dotnet</category>
      <category>braziliandevs</category>
    </item>
  </channel>
</rss>
