<?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>DEV Community: Marcelo Palladino "Palla"</title>
    <description>The latest articles on DEV Community by Marcelo Palladino "Palla" (@marcelofpalladino).</description>
    <link>https://dev.to/marcelofpalladino</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3030696%2Fc9590446-364e-4f08-be55-af5994dd71df.jpeg</url>
      <title>DEV Community: Marcelo Palladino "Palla"</title>
      <link>https://dev.to/marcelofpalladino</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/marcelofpalladino"/>
    <language>en</language>
    <item>
      <title>O detalhe que decide se o seu radar de tecnologia vive ou morre</title>
      <dc:creator>Marcelo Palladino "Palla"</dc:creator>
      <pubDate>Mon, 20 Jul 2026 13:26:17 +0000</pubDate>
      <link>https://dev.to/marcelofpalladino/o-detalhe-que-decide-se-o-seu-radar-de-tecnologia-vive-ou-morre-1o4i</link>
      <guid>https://dev.to/marcelofpalladino/o-detalhe-que-decide-se-o-seu-radar-de-tecnologia-vive-ou-morre-1o4i</guid>
      <description>&lt;p&gt;Em 2022, eu e o Francisco Edilton (&lt;a href="https://builder.aws.com/community/heroes/FranciscoEdilton" rel="noopener noreferrer"&gt;Chico, AWS Community Hero&lt;/a&gt;) nos encontrávamos todas as terças-feiras, sete da noite no horário do Brasil, para escrever a &lt;a href="https://www.herobuzz.com.br/arquivo/" rel="noopener noreferrer"&gt;HeroBuzz&lt;/a&gt;. Ele em Lisboa, eu em São Paulo. A newsletter era a desculpa. O que a gente realmente fazia era jogar conversa fora.&lt;/p&gt;

&lt;p&gt;A maioria das pessoas olha para uma hora marcada no calendário e pergunta quanto tempo aquilo vai durar. Comigo e com o Chico a pergunta sempre é como aproveitar melhor esse tempo. E era nessa "perda de tempo" que apareciam as histórias que compartilhamos na HeroBuzz. Coisas que a gente tinha visto dar errado, times que quebraram do mesmo jeito em organizações que não tinham nada a ver uma com a outra, decisões óbvias em retrospecto que ninguém tomou na hora. De vez em quando uma delas era boa demais para morrer ali, e um de nós dizia "e se a gente escrevesse sobre isso?".&lt;/p&gt;

&lt;p&gt;Foi assim que nasceu a &lt;a href="https://ckarchive.com/b/p9ueh9hvpe87" rel="noopener noreferrer"&gt;edição #33&lt;/a&gt;, em abril daquele ano. Na semana anterior tínhamos falado sobre o Technology Radar da ThoughtWorks e como ele é organizado. Naquela, pegamos o gancho para falar sobre por que uma organização poderia querer criar um radar próprio. Escrevemos sobre conhecimento concentrado em poucas cabeças, sobre o efeito copia e cola entre times, sobre stack que cresce sem gestão até virar problema de segurança. E terminamos com uma pergunta ao leitor:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nós conhecemos algumas organizações que se beneficiariam muito de um radar próprio. E você, acha que faz sentido para a sua realidade? Quais seriam os anéis e quadrantes do radar para sua organização?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Era muito fácil escrever aquilo. A gente estava olhando de fora.&lt;/p&gt;

&lt;p&gt;Há 45 dias assumi a direção de AI &amp;amp; Modernization na &lt;a href="https://www.dati.com.br/" rel="noopener noreferrer"&gt;Dati&lt;/a&gt; e estou liderando as iniciativas do Dati Labs. A pergunta voltou endereçada a mim.&lt;/p&gt;

&lt;h2&gt;
  
  
  Boas ideias param na máquina de quem as teve
&lt;/h2&gt;

&lt;p&gt;Essa cena eu já tinha visto se repetir em lugares que não tinham nada em comum, e levei tempo para entender que era sempre a mesma cena.&lt;/p&gt;

&lt;p&gt;Alguém chega numa conversa e diz que a tecnologia "X" está muito melhor que as outras tecnologias que usamos na empresa. Qual é a prova? Não existe. É uma impressão legítima, formada por alguém competente, que não vira decisão de ninguém porque não tem lastro nem lugar para morar. Ou alguém inicia uma iniciativa que outro time já estava tocando havia semanas. Repare que aí ninguém errou. Os dois times fizeram exatamente o que se esperava deles, com autonomia e velocidade. O desperdício aconteceu do mesmo jeito.&lt;/p&gt;

&lt;p&gt;Velocidade individual produz desperdício coletivo quando não existe um canal para as pessoas saberem umas das outras. E o problema é difícil de combater porque nunca se apresenta como falha. Ele se apresenta como movimento. Todo mundo ocupado, todo mundo entregando, e a organização andando menos do que se espera. É um dos sintomas clássicos de falta de coordenação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Duas formas de escalar engenharia
&lt;/h2&gt;

&lt;p&gt;Para simplificar a discussão aqui, podemos dizer que existem dois jeitos de organizar isso.&lt;/p&gt;

&lt;p&gt;O primeiro é o time opinativo. A stack está decidida e o desenvolvedor não gasta julgamento escolhendo ferramenta. Ele gasta julgamento no negócio. Isso escala muito bem e entrega rápido, e quem despreza esse modelo normalmente nunca precisou sustentar cinquenta times ao mesmo tempo.&lt;/p&gt;

&lt;p&gt;O segundo é o time onde experimentar é normal e até esperado. Você compra capacidade de descobrir coisas e paga em dispersão. No caso do Dati Labs, é o modelo certo. Nosso trabalho é justamente descobrir, e a gente não descobre nada sem experimentar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O Dati Labs é a área de AI &amp;amp; Modernization da Dati, e o que nos ocupa é a transformação do trabalho com IA agêntica. A pergunta que a gente quer responder é o que muda no jeito de fazer as coisas quando agentes passam a participar do trabalho para valer, e como isso vai se refletir nas organizações, nos processos e no software.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No Dati Labs, autonomia é uma escolha deliberada. É como acreditamos que se constrói um time que precisa explorar tecnologia em constante mudança. Só que essa escolha tem uma conta, e a conta é transparência.&lt;/p&gt;

&lt;h2&gt;
  
  
  A conta da autonomia
&lt;/h2&gt;

&lt;p&gt;Autonomia cria imediatamente dois desafios de comunicação que não existiam antes.&lt;/p&gt;

&lt;p&gt;O primeiro é para cima. Como comunicar à liderança o que o time está explorando? Se a resposta for uma apresentação que você monta de vez em quando, com o que lembrar na véspera, então a autonomia do time está apoiada na sua memória, e isso não sobrevive a nenhum trimestre difícil. E, principalmente, não sobrevive à sua saída. Líderes vêm e vão, a organização continua. Quem está acima de você não vai retomar decisões por má-fé. Vai retomar porque ninguém consegue defender o que não enxerga.&lt;/p&gt;

&lt;p&gt;O segundo é para os lados. Como permitir que seu time aprenda com outros times, e que outros times aprendam com o seu? Colaboração entre áreas não acontece por boa vontade. Acontece quando existe alguma coisa visível para colaborar em cima.&lt;/p&gt;

&lt;p&gt;Foi aí que a ficha caiu sobre o que eu mesmo tinha escrito quatro anos atrás. Autonomia sem transparência produz desperdício com aparência de produtividade. E a transparência que resolve isso não é um relatório produzido por alguém, porque relatório tem a assinatura e o recorte de quem o produziu. Tem que ser um artefato que pertence ao time, que qualquer um consegue ler, e que continua existindo independente de quem está na sala.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transparência morre quando é cara
&lt;/h2&gt;

&lt;p&gt;Essa é a parte que eu subestimei em 2022, e é onde a maioria das tentativas fracassa.&lt;/p&gt;

&lt;p&gt;Se contribuir com o artefato exigir ter uma opinião formada, ninguém contribui. A pessoa viu um lançamento interessante numa quinta-feira à noite, não tem tempo de avaliar, não quer ou não tem tempo para se posicionar sobre aquilo depois, e simplesmente não registra. A ideia volta a morrer na máquina de quem a teve, agora com um processo bonito por cima.&lt;/p&gt;

&lt;p&gt;O que resolveu isso para o Dati Labs foi separar duas coisas que parecem uma só. Registrar e julgar.&lt;/p&gt;

&lt;p&gt;Registrar precisa ser quase gratuito. Nome, categoria, link, data. Ninguém precisa ter opinião para colocar algo na fila, e colocar não significa endossar. Julgar é um passo separado e deliberado, que acontece depois, com calma e critério. Quando você mistura os dois, obriga cada pessoa a chegar com posição pronta, e o custo disso silencia justamente quem tem menos tempo e mais contexto de campo.&lt;/p&gt;

&lt;p&gt;Essa separação é o que tenho de mais transferível para oferecer aqui, e ela não depende de ferramenta nenhuma.&lt;/p&gt;

&lt;p&gt;Vale dizer o que pode dar errado do meu lado da mesa. Radar interno pode virar cemitério de blips (cada item registrado no radar) com uma facilidade impressionante, e quase sempre pelo mesmo motivo. Alguém confunde o artefato com o processo e começa a exigir campos, revisão e reunião de curadoria. O custo de entrada sobe, o mecanismo passa a servir a si mesmo, e o time volta a decidir por fora mantendo a aparência por dentro. Quando ninguém alimenta, a primeira hipótese que eu tenho que considerar é que eu tornei a entrada ou a avaliação cara demais.&lt;/p&gt;

&lt;p&gt;Baixar esse custo de entrada e de avaliação é, por si só, um desafio e tanto. E é exatamente o tipo de coisa que IA agêntica resolve muito bem. No Dati Labs a gente já começou a usar agentes para isso. Mas esse é assunto para outro texto.&lt;/p&gt;

&lt;h2&gt;
  
  
  O radar começa como espelho
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdgxl7rif8k8lp1dpxdxx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdgxl7rif8k8lp1dpxdxx.png" alt="Radar de Adoção do Dati Labs: gráfico circular com os mesmos quatro quadrantes e quatro anéis. Usando, Validando, Explorando e Descartado — representando a postura do Labs sobre o que já avaliou, o que está em produção e o que foi descartado." width="800" height="807"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheguei imaginando que o trabalho inicial seria montar um mecanismo para decidir o que vem pela frente. Errei a ordem.&lt;/p&gt;

&lt;p&gt;Quando você chega a uma organização que já entrega muito, não está diante de uma folha em branco. As pessoas já entregaram projetos, já resolveram problemas difíceis, já formaram opinião sólida sobre um monte de coisa. Já existe postura. Talvez ela só não seja recuperável por ninguém além de quem a formou. Fica viva no julgamento de cada pessoa e invisível para todas as outras ao mesmo tempo.&lt;/p&gt;

&lt;p&gt;Descobrir isso não depende de epifania. É conversando com as pessoas e entendendo o contexto. Influência se constrói conhecendo as pessoas e o terreno, e eu passei as primeiras semanas aprendendo bem mais com o meu time do que o contrário. É um time talentoso e eu tenho sorte de trabalhar com eles.&lt;/p&gt;

&lt;p&gt;Então o primeiro trabalho de um radar não é decidir nada. É dar nome ao que já é verdade. Você registra a postura que o time já tem antes de começar a triar o que chega de fora, e só depois de existir esse espelho é que faz sentido montar o filtro.&lt;/p&gt;

&lt;h2&gt;
  
  
  A matriz de fronteira e relevância do Dati Labs
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk5todpgiwz8d53grhulk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk5todpgiwz8d53grhulk.png" alt="Radar de Fronteira do Dati Labs: gráfico circular dividido em quatro quadrantes (Técnicas, Ferramentas, Plataformas &amp;amp; Serviços, Modelos &amp;amp; Frameworks) e quatro anéis concêntricos — Mergulhar, Acompanhar, Observar e Passar. Com lançamentos numerados triados por fronteira e relevância." width="800" height="775"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quando o filtro entra em cena, a tentação é ordenar tudo por novidade. Achamos que essa é a régua errada, e ela é o motivo de tanta gente boa gastar a semana correndo atrás do que está mais barulhento na timeline. O hype pelo hype.&lt;/p&gt;

&lt;p&gt;No Dati Labs, a gente usa duas perguntas, e a segunda pesa mais que a primeira.&lt;/p&gt;

&lt;p&gt;A primeira é sobre o &lt;strong&gt;potencial de mudança&lt;/strong&gt;: &lt;em&gt;isso muda o teto do que era possível, reabrindo casos que a gente considerava inviáveis, ou melhora muito alguma coisa que já dava para fazer?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A segunda é sobre &lt;strong&gt;relevância&lt;/strong&gt;: &lt;em&gt;isso toca os nossos clientes e/ou a nossa stack, ou é interessante para o mundo e distante do que a gente entrega e da estratégia?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Percebe? No limite, tudo é interessante. Então ter uma régua de relevância é fundamental para não desperdiçar energia.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Perto do nosso jogo&lt;/th&gt;
&lt;th&gt;Longe do nosso jogo&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Muda o teto do que é possível&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Anel 1: Mergulhar.&lt;/strong&gt; Testar agora.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Anel 3: Observar.&lt;/strong&gt; De longe.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Melhora o que já era possível&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Anel 2: Acompanhar.&lt;/strong&gt; De perto, sem correr.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Anel 4: Passar.&lt;/strong&gt; Registrar e seguir.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A relevância pesar mais é o que muda o resultado, o que é um tanto contraintuitivo, se você pensar bem. Mas vem comigo, uma coisa impressionante que não toca no seu jogo, que não conversa com a  estratégia de negócio, merece menos energia do que uma coisa entediante que toca. Faz sentido? Pense nisso como &lt;strong&gt;antídoto&lt;/strong&gt; para o "isso aqui está muito melhor agora" solto numa conversa de corredor, porque a régua nos leva a completar a frase.&lt;/p&gt;

&lt;p&gt;"Melhor para quê? Melhor para quem? Melhor quanto?"&lt;/p&gt;

&lt;p&gt;Na mesma semana avaliamos duas novidades da mesma categoria, do mesmo fornecedor. As duas eram boas. Mas apenas uma reabria casos de uso que antes eram inviáveis para nós. A outra apenas melhorava uma solução que já funcionava. Pela régua do hype, elas competiriam pela mesma priorização. Pela nossa régua de fronteira x relevância, tiveram destinos diferentes. Uma foi para teste imediato, para o mergulho, enquanto a outra foi para acompanhamento. Nenhum dos dois foi ignorado. Registrar o segundo é o que impede o time de reavaliar a mesma coisa do zero daqui a três meses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Créditos
&lt;/h2&gt;

&lt;p&gt;Nada disso é invenção nossa. O Technology Radar da ThoughtWorks é a técnica original, e a ThoughtWorks mantém o &lt;a href="https://github.com/thoughtworks/build-your-own-radar" rel="noopener noreferrer"&gt;build-your-own-radar&lt;/a&gt; aberto justamente para que qualquer empresa monte o seu.&lt;/p&gt;

&lt;p&gt;O que mudou não foi a técnica, foi a pressão. O Technology Radar é um retrato curado e periódico. Ele não foi desenhado para a vazão diária de lançamentos que a gente vive hoje, o que não é defeito nenhum, é escopo. Na prática, quando a entrada acelera desse jeito, você precisa de um lugar separado para o que chegou e ainda não foi julgado. Se a fila de triagem se misturar com a lista de posturas, as duas perdem sentido, porque você deixa de saber o que foi decidido e o que só foi anotado. Foi por isso que acabamos com dois níveis, um para o que está chegando e outro para o que já é postura, com uma ponte entre eles para o que sobrevive ao teste.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que ainda não sabemos
&lt;/h2&gt;

&lt;p&gt;Estamos bem no começo disso. O que queremos construir é justamente uma forma de fazer com que as pessoas do time da Dati se sintam confortáveis em contribuir, mesmo sem certeza de que aquilo vale a pena. O mecanismo é o meio para que isso aconteça, não o objetivo.&lt;/p&gt;

&lt;p&gt;Em 2022 eu e o Chico perguntamos aos leitores quais seriam os anéis e quadrantes do radar da empresa deles. A pergunta continua valendo. Só que hoje eu sei que escolher os anéis é a parte fácil. A parte difícil é alimentar e manter aquilo numa terça-feira comum, com entrega pressionando e ninguém cobrando.&lt;/p&gt;

&lt;p&gt;Me pergunte de novo daqui a seis meses.&lt;/p&gt;




&lt;p&gt;Se você também está pensando em como a IA agêntica transforma o trabalho e as organizações, &lt;a href="https://www.linkedin.com/in/mfpalladino/" rel="noopener noreferrer"&gt;entre em contato comigo&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>leadership</category>
      <category>software</category>
      <category>career</category>
    </item>
    <item>
      <title>Speech-to-Speech AI: From Dr. Sbaitso to Amazon Nova Sonic</title>
      <dc:creator>Marcelo Palladino "Palla"</dc:creator>
      <pubDate>Wed, 09 Apr 2025 14:34:14 +0000</pubDate>
      <link>https://dev.to/aws/speech-to-speech-ai-from-dr-sbaitso-to-amazon-nova-sonic-51nc</link>
      <guid>https://dev.to/aws/speech-to-speech-ai-from-dr-sbaitso-to-amazon-nova-sonic-51nc</guid>
      <description>&lt;p&gt;I will never forget a certain night in the 1990s. It must have been around 1992 or 1993 - I was at my friend Junior's house, crowded with a bunch of other kids around his parents' computer. I am pretty sure it was a 386, or maybe a 286? All I knew back then was that it had a fancy multimedia kit. The source of our fascination was a program called Dr. Sbaitso.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fnuh29f3mh6gww5ka07ta.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fnuh29f3mh6gww5ka07ta.jpg" alt="Dr. Sbaitso"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Released by Creative Labs, Dr. Sbaitso was one of the first computer chat programs, created to demonstrate the capabilities of the Sound Blaster sound card. The name is actually an acronym for "Sound Blaster Artificial Intelligent Text to Speech Operator" &lt;em&gt;(to be honest, I only learned it while I was writing this article)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The system simulated a digital psychotherapist and became known for its sometimes strange responses and its characteristic robotic voice. It was quite limited in its interactions. One of its most famous phrases was "TELL ME MORE ABOUT THAT”, which it frequently repeated during conversations, back then, with our cluelessness, it felt we were living in a sci-fi movie. &lt;/p&gt;

&lt;p&gt;"Can you fall in love?" while everyone laughed beside me.&lt;/p&gt;

&lt;p&gt;"TELL ME MORE ABOUT THAT", it would respond with its characteristic artificial voice.&lt;/p&gt;

&lt;p&gt;We would not give up. We spent hours making up stories, creating scenarios, trying to convince that digital therapist to fall in love with one of our friends. With each disconnected response, we laughed more and tried even more hard.&lt;/p&gt;

&lt;p&gt;It's funny how these memories stick with you. That clunky old PC with its robotic voice seems almost prehistoric now, but it was pure magic to us back then. Three decades later, I'm still amazed every time I think about how far we've come. During this time, the way people and machines interact has changed dramatically. From those first tries with voice synthesis, through different assistant experiments, up to the AI assistants that are now just part of our daily lives. And now here I am, working with &lt;a href="https://aws.amazon.com/ai/generative-ai/nova/speech?trk=92ed481f-0929-405b-acc1-5857a9852861&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon Nova Sonic&lt;/a&gt; and &lt;a href="https://aws.amazon.com/bedrock?trk=92ed481f-0929-405b-acc1-5857a9852861&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon Bedrock&lt;/a&gt;, building the kind of natural conversations I could only dream about back then.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Amazon Nova Sonic
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/ai/generative-ai/nova/speech?trk=92ed481f-0929-405b-acc1-5857a9852861&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon Nova Sonic&lt;/a&gt; is a model that does everything together. Instead of the way where you needed different models and separate steps for STT (Speech-to-Text), processing, and TTS (Text-to-Speech), Amazon Nova Sonic just handles everything in one go, processing audio real-time both ways through complete two-way streaming. This means you can build systems that keep all the important stuff like tone, emotions, and how people actually talk throughout the whole conversation.&lt;/p&gt;

&lt;p&gt;Let me show you a quick demo to see how this works. Meet &lt;strong&gt;DR ANSMUE&lt;/strong&gt; &lt;em&gt;(Amazon Nova Sonic Model Usage Example)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Frpbtrm424xftnp9n1fqp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Frpbtrm424xftnp9n1fqp.jpg" alt="DR ANSMUE sample in action"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Yeah, I know it is not super original. But cut me some slack, ok?&lt;/em&gt; In this example, users can submit their code and chat with our "code therapist" about whatever code they sent in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fyn0639jo885f8qkg4gda.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fyn0639jo885f8qkg4gda.png" alt="DR ANSMUE architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Under the hood&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;What I'm going to show you here is based on the Bidirectional Audio Streaming sample (the one using Amazon Nova Sonic and Amazon Bedrock with TypeScript) that you can find in the &lt;a href="https://github.com/aws-samples/amazon-nova-samples/tree/main/speech-to-speech" rel="noopener noreferrer"&gt;Amazon Nova Sonic Speech-to-Speech Model Samples&lt;/a&gt;. So, instead of getting into all the specific technical details of this sample, I'll focus on walking you through the key things you need to know for build this kind of application.&lt;/p&gt;

&lt;p&gt;When the user starts talking, the web frontend gets the audio from the microphone using WebAudio API and sends it to the server through WebSockets. On the server side, we have got the &lt;code&gt;StreamSession&lt;/code&gt; class that manages the audio chunks and puts them in line for processing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;audioInput&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;audioData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Convert base64 string to Buffer&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;audioBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;audioData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Stream the audio&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;streamAudio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;audioBuffer&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;This works in collaboration with the &lt;code&gt;S2SBidirectionalStreamClient&lt;/code&gt; class, which handles the back-and-forth communication using &lt;code&gt;AsyncIterable&lt;/code&gt; to create a two-way stream with Amazon Bedrock, using the new capabilities of Amazon Bedrock SDK.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;createSessionAsyncIterable&lt;/code&gt; method in &lt;code&gt;S2SBidirectionalStreamClient&lt;/code&gt; creates an iterator that feeds into the &lt;code&gt;InvokeModelWithBidirectionalStreamCommand&lt;/code&gt;, a new invoke way from the Amazon Bedrock SDK, sending those audio chunks (in base64) to Amazon Nova Sonic. At the same time, processResponseStream handles what comes back from the Amazon Berock, figuring out the audioOutput and textOutput it receives.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;createSessionAsyncIterable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sessionId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;AsyncIterable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InvokeModelWithBidirectionalStreamInput&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asyncIterator&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IteratorResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InvokeModelWithBidirectionalStreamInput&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;// Wait for items in the queue or close signal&lt;/span&gt;
          &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;race&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
              &lt;span class="nf"&gt;firstValueFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queueSignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))),&lt;/span&gt;
              &lt;span class="nf"&gt;firstValueFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closeSignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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="c1"&gt;// Get next item from the session's queue&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextEvent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shift&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Actual invocation of the bidirectional stream command&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bedrockRuntimeClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InvokeModelWithBidirectionalStreamCommand&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;modelId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;amazon.nova-sonic-v1:0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;asyncIterable&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;S2SBidirectionalStreamClient&lt;/code&gt; keeps track of what is happening using the data structure &lt;code&gt;SessionData&lt;/code&gt;, controlling signals, and event handlers. When the model comes back with something, it goes back through the same WebSocket to the frontend, where the browser plays it using WebAudio API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;processResponseStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sessionId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&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="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;textResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TextDecoder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jsonResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;textResponse&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="nx"&gt;jsonResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;textOutput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sessionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;textOutput&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;jsonResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textOutput&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsonResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;audioOutput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sessionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;audioOutput&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;jsonResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;audioOutput&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="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;All of this happens right away. The &lt;code&gt;streamAudioChunk&lt;/code&gt; method in &lt;code&gt;StreamSession&lt;/code&gt; manages a queue through &lt;code&gt;audioBufferQueue&lt;/code&gt;, which avoids things from getting overloaded and keeps all the audio data in the right order, so conversations feel natural and smooth.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;processAudioQueue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isProcessingAudio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Process chunks in the queue&lt;/span&gt;
  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;audioBufferQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;audioChunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;audioBufferQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shift&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="nx"&gt;audioChunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;streamAudioChunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sessionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;audioChunk&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="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make all of this work smoothly, we are using &lt;strong&gt;HTTP/2&lt;/strong&gt; to call the Amazon Bedrock. The cool thing is that, unlike HTTP, HTTP/2 lets us send multiple streams over the same connection. That is helpful to keep the audio flowing in both directions &lt;br&gt;
without delays. Another nice thing is performance. it compresses headers and figures out which parts to prioritize, so everything feels quicker and more natural. Especially when there is a lot going on at once.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nodeClientHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NodeHttp2Handler&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;requestTimeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;sessionTimeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;disableConcurrentStreams&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;maxConcurrentStreams&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bedrockRuntimeClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BedrockRuntimeClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;us-east-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;requestHandler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;nodeClientHandler&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;In a nutshell&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;It might look complex at first, but in a nutshell, what is happening is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User =&amp;gt; Server: User speaks into their microphone, and their voice travels to the server.&lt;/li&gt;
&lt;li&gt;Server =&amp;gt; Amazon Bedrock: The server forwards user voice to Amazon Bedrock, but &lt;strong&gt;&lt;em&gt;doesn't wait&lt;/em&gt;&lt;/strong&gt; for user to finish speaking.&lt;/li&gt;
&lt;li&gt;Amazon Bedrock =&amp;gt; Server: As soon as it can, Amazon Bedrock starts sending responses back to the server.&lt;/li&gt;
&lt;li&gt;Server =&amp;gt; User: The server immediately forwards the responses to user browser, which plays them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This all happens in near real-time, creating a natural conversation where responses can overlap with user speaking, just like in human conversations.&lt;/p&gt;

&lt;h2&gt;
  
  
  New possibilities
&lt;/h2&gt;

&lt;p&gt;It opens up a bunch of possibilities that used to feel super hard to achieve. Imagine calling customer support and being able to interrupt and actually fix something mid-sentence, instead of waiting for any pauses to finish. Or think about a virtual assistant joining your team meeting and just keeping up, responding like a real person instead of lagging behind.&lt;/p&gt;

&lt;p&gt;This kind of thing could be huge for accessibility too. People with visual or motor impairments could interact with systems more easily. And in classrooms, virtual tutors could actually listen and answer questions like a real conversation. Even live translation could feel smoother, like you’re actually talking to someone, not just waiting for a machine to catch up.&lt;/p&gt;

&lt;p&gt;Start building with AWS SDK's bidirectional streaming API, Amazon Nova Sonic and Amazon Bedrock today. Check the &lt;a href="https://aws.amazon.com/developer/generative-ai/bedrock?trk=92ed481f-0929-405b-acc1-5857a9852861&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;resources for developers to build, deploy, and scale AI-powered applications&lt;/a&gt; and &lt;a href="https://github.com/aws-samples/amazon-nova-samples/tree/main/speech-to-speech" rel="noopener noreferrer"&gt;Amazon Nova Sonic Speech-to-Speech Model Samples&lt;/a&gt; to learn more about how to implement it in your own applications.&lt;/p&gt;

&lt;p&gt;As I write about these possibilities, I find myself increasingly eager to explore their practical applications. But before diving into new projects, I &lt;strong&gt;need&lt;/strong&gt; to try this one more time with DR ANSMUE:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“Hey Doc, can you fall in love?” 💔&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/xrgdImGP0t4"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Made with ♥ from DevRel&lt;/p&gt;

</description>
      <category>amazonbedrock</category>
      <category>amazonnova</category>
      <category>ai</category>
      <category>speechtospeech</category>
    </item>
  </channel>
</rss>
