https://a.storyblok.com/f/270183/721112/d9d03c8e1e/p2p-voice-journal-featured.png

Criando um diário de voz para o Next Web

Publicado em May 13, 2021

Tempo de leitura: 7 minutos

A internet é algo maravilhoso. Podemos criar e compartilhar informações com mais facilidade do que em qualquer outro momento da história da humanidade.

Escrevendo um tutorial para o @NexmoDev enquanto estou a 35.000 pés acima do Atlântico #devrellife pic.twitter.com/mvxGDuEDky

— Aaron Bassett - em que fuso horário estamos? (@aaronbassett) 15 de maio de 2018

No entanto, grande parte do que criamos fica confinada em “jardins murados”; isso é a antítese da ideia original da WWW. A quebra dessas barreiras é algo sobre o qual Tim Berners-Lee vem falando desde, pelo menos, 2009!

Na verdade, os dados dizem respeito às nossas vidas. É só... você entra na sua rede social, a sua favorita, e diz: “Este é meu amigo”. Bing! Relacionamento. Dados. Você diz: “Esta foto é sobre... ela retrata essa pessoa”. Bing! Isso são dados. Dados, dados, dados. Toda vez que você faz algo na rede social, ela coleta esses dados e os utiliza — redirecionando-os — para tornar a vida de outras pessoas mais interessante no site. Mas, quando você acessa outro site de dados interligados — digamos que seja um site sobre viagens — e diz: “Quero enviar essa foto para todas as pessoas desse grupo”, você não consegue ultrapassar as barreiras.

Sir Tim Berners-Lee

Na verdade, a descentralização tem sido um aspecto fundamental da WWW desde sua criação.

Descentralização: Não é necessária nenhuma autorização de uma autoridade central para publicar qualquer coisa na web; não há um nó central de controle e, portanto, não há um único ponto de falha… nem um “kill switch”! Isso também implica liberdade contra a censura e a vigilância indiscriminadas.

Web Foundation, História da Web

Apresentando a web de pessoa a pessoa

Voice Journal ScreenshotVoice Journal Screenshot

Com a rede ponto a ponto, não é necessário nenhum servidor. Cada visitante do seu site se torna um participante da rede. Eles se conectam diretamente entre si e compartilham os arquivos do seu site uns com os outros. Isso não só ajuda a manter o seu site no ar, como também proporciona liberdade contra a censura indiscriminada.

Vamos ver como podemos usar o protocolo Dat com a Voice API da Nexmo para criar um site distribuído para hospedar um diário em áudio. Você pode baixar o código deste exemplo no GitHub.

Fluxo do processo

O fluxo do processo do nosso aplicativo é simples. Quando ligamos para o nosso Número Virtual da Nexmo, ele grava o áudio como um MP3 e notifica nosso servidor de que há uma nova gravação. Em seguida, quando nosso servidor recebe a notificação da Nexmo, ele baixa o arquivo MP3 e o adiciona ao nosso arquivo, sendo automaticamente compartilhado com todos os pares que utilizam o protocolo Dat.

O objeto Nexmo Call Control e a ação de gravação

Gravar o áudio é extremamente simples com a Nexmo. Criamos um arquivo NCCO com uma única record ação. Você também pode usar a funcionalidade TTS para reproduzir uma mensagem antes da gravação; optei por não fazer isso e, em vez disso, instruí o Nexmo a emitir um bipe quando estiver pronto para gravar. Muito parecido com uma secretária eletrônica.

@hug.get('/')
def ncco():
    return [
        {
            "action": "record",
            "eventUrl": ["<SERVER URL>/recordings"],
            "endOnKey": "*",
            "beepStart": True
        }
    ]

No código acima, estou usando o Hug para criar um endpoint JSON para enviar meu arquivo NCCO para a API da Nexmo. Para mais informações sobre como criar aplicativos de voz com a Nexmo (e para saber mais sobre o que é um arquivo NCCO), leia alguns dos meus tutoriais anteriores:

Também falo mais sobre as Applications de voz da Nexmo nos meus webinars de programação ao vivo; isso acontece por volta dos 20 minutos:

Salvar a gravação

Assim que a chamada terminar ou o usuário pressionar ""* A Nexmo nos notifica sobre a nova gravação por meio do webhook que especificamos como eventUrl no código acima. A solicitação enviada ao nosso webhook contém o recording_url que podemos usar para baixar o arquivo MP3. No entanto, primeiro precisamos nos autenticar no Nexmo para garantir que temos permissão para baixar a gravação. Usamos JWTs para autenticação.

@hug.post('/recordings')
def recordings(recording_url, recording_uuid):
    iat = int(time.time())
    now = datetime.datetime.now()

    with open('nexmo_private.key', 'rb') as key_file:
        private_key = key_file.read()

    payload = {
        'application_id': os.environ['APPLICATION_ID'],
        'iat': iat,
        'exp': iat + 60,
        'jti': str(uuid.uuid4()),
    }

    token = jwt.encode(payload, private_key, algorithm='RS256')

    recording_response = requests.get(
        recording_url,
        headers={
            'Authorization': b'Bearer ' + token,
            'User-Agent': 'voice-journal'
        }
    )
    if recording_response.status_code == 200:
        recordingfile = f'./site/recordings/{now.year}/{now.month}/{recording_uuid}.mp3'
        os.makedirs(os.path.dirname(recordingfile), exist_ok=True)

        with open(recordingfile, 'wb') as f:
            f.write(recording_response.content)

A maior parte do código acima é para a autenticação JWT [*é, alguém realmente deveria facilitar isso no cliente Python… ?]. Depois de baixarmos a gravação, salvamos o arquivo MP3, tomando o cuidado de manter nosso arquivo bem organizado.

/recordings/<current year>/<current month>/<recording uuid>.mp3

Ao organizar nossas gravações dessa forma no disco, mesmo sem a interface do nosso aplicativo, podemos facilmente localizar e ouvir uma gravação de um determinado dia.

Distribuição de nossas gravações

Existem duas formas principais de divulgar nosso site por meio de Dat; usando a CLI do Datou pelo navegador Beaker. Para simplificar, vamos usar o Beaker neste exemplo. No entanto, se você quiser executar seu webhook em um servidor ou como uma função sem servidor, use a CLI do Dat. Tara Vancil tem um ótimo artigo sobre como eles usa a CLI do Dat para publicar atualizações em seu blog (versão do Dat). Uma coisa a se ter em mente é que o front-end do nosso aplicativo usa algumas APIs específicas do Beaker para interagir com nosso arquivo e exibir informações sobre o swarm; ao contrário do site da Tara, ele não funciona em um navegador comum, portanto, você não precisa do dathttpd.

Se você ainda não fez isso, deveria baixar o Beaker agora.

Junte-se ao meu Swarm

Observação: Assim como no BitTorrent e em outros protocolos P2P, os membros de um swarm podem, por necessidade, ver os endereços IP dos outros membros. Lembre-se de que se trata de uma distribuição ponto a ponto, que não passa por um serviço centralizado. Você pode pular a próxima seção se não se sentir à vontade para compartilhar seu endereço IP com outros participantes do swarm.

Abra o seguinte dat:// link no Beaker: dat://8354c381e6f859e57ef6979af7e287acf3d528d8463f54774c36b6bc8aa514d6/

Parabéns, agora você faz parte do meu enxame e pode distribuir as gravações de áudio para outros visitantes. Você é (um dos) meus servidores web, muito obrigado!

No entanto, ao fechar o navegador, você sai do swarm. Os arquivos permanecem no seu computador, mas você não os está mais distribuindo para outros visitantes. Para garantir que haja sempre pelo menos um peer disponível, adicionei o arquivo a #_hashbase.

A interface do usuário do aplicativo

Você não precisa criar uma interface de usuário para acessar suas gravações. O Beaker cria uma interface simples para a gente usar caso nosso diretório de arquivo não contenha um arquivo de índice. Ela é funcional, mas não é muito bonita. Podemos fazer melhor.

Directory listing rendered by Beaker BrowserDirectory listing rendered by Beaker Browser

Nosso front-end é um aplicativo Vue, que utiliza o sistema de design Vonage Volta. O Volta é o mesmo sistema de design que usamos na recente reformulação do Nexmo Dashboard. Infelizmente, o Volta não é de código aberto, pelo menos não ainda.

Também utilizamos algumas APIs específicas do Beaker para interagir com nosso arquivo.

const archive = new DatArchive(window.location)
let allRecordings = await archive.readdir('/recordings', {recursive: true, stat: true})

No código acima, consultamos nosso arquivo, lendo o conteúdo do diretório de gravações e filtrando todos os arquivos que não sejam MP3. A stat opção instrui o Beaker a executar stat() em cada entrada e retorne com {name:, stat:}.

Outro elemento digno de destaque na página são os quadros informativos na parte superior da página.

Screenshot of swarm information UIScreenshot of swarm information UI

Utilizamos outra API do Beaker para recuperar essas informações, getInfo()

async peers () {
    return await this.archiveInfo.peers
},
async version () {
    return await this.archiveInfo.version
},
async mtime () {
    let timestamp = await this.archiveInfo.mtime
    return moment(timestamp).startOf().fromNow()
},
async filesize () {
    let size = await this.archiveInfo.size
    return filesize(size, {round: 2})
}

Histórico do arquivo

O protocolo Dat garante que o arquivo seja assinado pelo autor e que sua integridade possa ser verificada por meio de consultas a pares da rede (uniformidade de distribuição). Apenas uma versão do histórico do arquivo pode ser distribuída. Se for constatado que um arquivo Dat assinado difere da cópia assinada de um par, ele é considerado corrompido, pois o conteúdo divergente poderia indicar um ataque direcionado pelo autor do Dat. É importante que todos os usuários recebam o mesmo conteúdo, e é por isso que o Dat possui verificação de integridade integrada.

Beaker Browser, publique software com segurança

History log screenshotHistory log screenshot

Usando as APIs da Web do Beaker, podemos consultar e exibir esse registro das alterações feitas em nosso arquivo; esse registro mostra até mesmo se o autor excluiu alguma entrada do diário.

archiveHistory: {
    async get () {
    const archive = new DatArchive(window.location)
    const completeHistory = archive.history({start: 0, reverse: true})
    return completeHistory
    }
},

Saiba mais

Compartilhar:

https://a.storyblok.com/f/270183/150x150/a3d03a85fd/placeholder.svg
Aaron BassettEx-funcionários da Vonage

Aaron era um defensor de desenvolvedores na Nexmo. Engenheiro de software experiente e aspirante a artista digital, Aaron costuma ser visto criando coisas com código ou com eletrônica; às vezes, os dois. Geralmente, dá para perceber quando ele está trabalhando em algo novo pelo cheiro de componentes queimando no ar.