https://d226lax1qjow5r.cloudfront.net/blog/blogposts/next-web-voice-journal-python-vue-javascript-dr/p2p-voice-journal-featured.png

Erstellen eines Voice-Journals für das Next Web

Zuletzt aktualisiert am May 13, 2021

Lesedauer: 6 Minuten

Das World Wide Web ist eine wundersame Sache. Wir können Informationen leichter erstellen und austauschen als je zuvor in der Geschichte der Menschheit.

Schreiben eines Tutorials für die @NexmoDev Blog in 35.000 Fuß Höhe über dem Atlantik #devrellife pic.twitter.com/mvxGDuEDky

- Aaron Bassett - welche Zeitzone ist es? (@aaronbassett) May 15, 2018

Vieles von dem, was wir erschaffen, lebt jedoch innerhalb von ummauerten Gärten; das ist das Gegenteil der ursprünglichen Idee des www. Diese ummauerten Gärten aufzubrechen, ist etwas, worüber Tim Berners Lee mindestens seit 2009 spricht!

Tatsächlich geht es bei den Daten um unser Leben. Sie loggen sich einfach in Ihr soziales Netzwerk ein, Ihre Lieblingswebsite, und sagen: "Das ist mein Freund". Bing! Beziehung. Daten. Sie sagen: "Dieses Foto zeigt diese Person." Bing! Das sind Daten. Daten, Daten, Daten. Jedes Mal, wenn Sie etwas auf der Social-Networking-Site tun, nimmt die Social-Networking-Site Daten und verwendet sie - zweckentfremdet - und nutzt sie, um das Leben anderer Menschen auf der Site interessanter zu machen. Aber wenn man auf eine andere verknüpfte Datenseite geht - und sagen wir mal, es geht um Reisen - und sagt: "Ich möchte dieses Foto an alle Leute in dieser Gruppe schicken", kommt man nicht über die Mauern hinweg.

- Sir Tim Berners-Lee

Tatsächlich ist die Dezentralisierung von Anfang an ein grundlegender Aspekt des www gewesen.

Dezentralisierung: Es ist keine Erlaubnis einer zentralen Behörde erforderlich, um etwas ins Netz zu stellen, es gibt keinen zentralen Kontrollknoten und somit keinen "Single Point of Failure" ... und keinen "Kill Switch"! Dies bedeutet auch die Freiheit von willkürlicher Zensur und Überwachung.

- Web Foundation, Geschichte des Webs

Einführung in das Person-to-Person-Web

Voice Journal ScreenshotVoice Journal Screenshot

Für das Person-to-Person-Web ist kein Server erforderlich. Jeder Besucher Ihrer Website wird zu einem Peer im Schwarm. Sie verbinden sich direkt miteinander und teilen die Dateien Ihrer Website mit anderen. Dies trägt nicht nur dazu bei, dass Ihre Website online bleibt, sondern es schafft auch Freiheit von willkürlicher Zensur.

Schauen wir uns an, wie wir das Dat-Protokoll mit Nexmo's Voice API verwenden können, um eine verteilte Website zu erstellen, die ein Audio-Journal enthält. Sie können den Code für dieses Beispiel auf Github herunterladen.

Prozessablauf

Der Prozessablauf für unsere Anwendung ist einfach. Wenn wir unsere virtuelle Nexmo-Nummer anrufen, nimmt sie den Ton als MP3 auf und benachrichtigt unseren Server, dass es eine neue Aufnahme gibt. Wenn unser Server dann die Benachrichtigung von Nexmo erhält, lädt er die MP3-Datei herunter und fügt sie unserem Archiv hinzu, und sie wird automatisch mit allen Peers geteilt, die das Dat-Protokoll verwenden.

Nexmo Call Control Objekt und die Aufzeichnungsaktion

Die Aufnahme von Audio ist besonders einfach mit Nexmo. Wir erstellen eine NCCO-Datei mit einer einzigen record Aktion. Vielleicht möchten Sie auch die TTS-Funktion nutzen, um eine Nachricht vor der Aufnahme abzuspielen. Ich habe mich dagegen entschieden und Nexmo angewiesen, einen Piepton abzuspielen, wenn es bereit ist, aufzunehmen. Ähnlich wie ein Anrufbeantworter.

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

In dem obigen Code verwende ich Hug, um einen JSON-Endpunkt zu erstellen um meine NCCO-Datei an die Nexmo-API zu übergeben. Für weitere Informationen zur Erstellung von Voice Applications mit Nexmo (und für Details darüber, was eine NCCO-Datei ist), lesen Sie bitte einige meiner früheren Tutorials:

Ich erkläre auch mehr über Nexmo Voice Applications in meinen Live-Coding-Webinaren; es sind etwa 20 Minuten:

Speichern der Aufnahme

Sobald der Anruf beendet ist oder der Benutzer die Taste ""* Nexmo benachrichtigt uns über die neue Aufnahme über den Webhook, den wir als eventUrl im obigen Code angegeben haben. Die Anfrage an unseren Webhook enthält die recording_url die wir verwenden können, um die MP3-Datei herunterzuladen. Zuerst müssen wir uns jedoch bei Nexmo authentifizieren, um sicherzustellen, dass wir die Erlaubnis haben, die Aufnahme herunterzuladen. Wir verwenden JWTs für die Authentifizierung.

@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)

Der größte Teil des obigen Codes ist für die JWT-Authentifizierung [*ja, jemand sollte das wirklich im Python-Client einfacher machen... ?]. Nachdem wir die Aufnahme heruntergeladen haben, speichern wir die MP3-Datei, wobei wir darauf achten, dass unser Archiv schön geordnet bleibt.

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

Indem wir unsere Aufzeichnungen auf diese Weise auf der Festplatte strukturieren, können wir auch ohne unser Anwendungsfrontend leicht eine Aufzeichnung eines bestimmten Tages finden und anhören.

Vertrieb unserer Aufzeichnungen

Es gibt zwei Hauptwege für die Verbreitung unserer Website über Dat; über die Dat CLIoder über den Beaker-Browser. Der Einfachheit halber werden wir in diesem Beispiel Beaker verwenden. Wenn Sie Ihren Webhook jedoch auf einem Server oder als serverlose Funktion ausführen möchten, dann verwenden Sie die Dat CLI. Tara Vancil hat einen großartigen Artikel darüber, wie sie Dat CLI verwendet, um Updates in ihrem Blog zu veröffentlichen (dat-Version). Eine Sache, die zu beachten ist, ist, dass unser Anwendungsfrontend einige Beaker-spezifische APIs verwendet, um mit unserem Archiv zu interagieren und Informationen über den Schwarm anzuzeigen; im Gegensatz zu Taras Website funktioniert sie nicht in einem normalen Browser, Sie brauchen also nicht dathttpd.

Wenn Sie es nicht schon getan haben, sollten Sie Beaker jetzt herunterladen.

Meinem Schwarm beitreten

Hinweis: Ähnlich wie bei BitTorrent und anderen P2P-Protokollen können die Mitglieder eines Schwarms zwangsläufig die IP-Adressen der anderen Mitglieder sehen. Denken Sie daran, dass es sich um eine Peer-to-Peer-Verteilung handelt, die nicht über einen zentralisierten Dienst läuft. Sie können den nächsten Abschnitt überspringen, wenn Sie Ihre IP-Adresse nicht mit anderen Schwarmteilnehmern teilen wollen.

Öffnen Sie den folgenden dat:// Link in Beaker: dat://8354c381e6f859e57ef6979af7e287acf3d528d8463f54774c36b6bc8aa514d6/

Herzlichen Glückwunsch, Sie sind jetzt Mitglied in meinem Schwarm und können die Audioaufnahmen an andere Besucher weitergeben. Sie sind (einer) meiner Webserver, vielen Dank!

Wenn Sie jedoch Ihren Browser schließen, verlassen Sie den Schwarm. Die Dateien verbleiben auf Ihrem Computer, aber Sie geben sie nicht mehr an andere Besucher weiter. Um sicherzustellen, dass immer mindestens ein Peer verfügbar ist, habe ich das Archiv zu #_hashbase.

Das Frontend der Anwendung

Sie müssen keine Benutzeroberfläche für den Zugriff auf Ihre Aufzeichnungen erstellen. Beaker erstellt eine einfache Schnittstelle, die wir verwenden können, wenn unser Archivverzeichnis keine Indexdatei enthält. Sie ist funktional, aber nicht sehr hübsch. Wir können es besser machen.

Directory listing rendered by Beaker BrowserDirectory listing rendered by Beaker Browser

Unser Frontend ist eine Vue-Anwendungdie das Vonage Volta Designsystem verwendet. Volta ist das gleiche Designsystem, das wir bei der kürzlichen Neugestaltung des Nexmo Dashboards verwendet haben. Leider ist Volta nicht Open Source, zumindest noch nicht.

Wir verwenden auch einige Beaker-spezifische APIs für die Interaktion mit unserem Archiv.

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

Im obigen Code fragen wir unser Archiv ab, lesen den Inhalt unseres Aufnahmeverzeichnisses und filtern alle Dateien heraus, die keine MP3s sind. Die Option stat Option weist Beaker an, die Funktion stat() für jeden Eintrag auszuführen und mit {name:, stat:}.

Ein weiterer bemerkenswerter Teil der Seite sind die Informationsfelder am oberen Rand der Seite.

Screenshot of swarm information UIScreenshot of swarm information UI

Wir verwenden eine andere Beaker-API, um diese Informationen abzurufen, 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})
}

Archiv Geschichte

Das Dat-Protokoll stellt sicher, dass das Archiv vom Autor signiert ist und durch die Abfrage von Netzwerk-Peers auf Korrektheit überprüft werden kann (Einheitlichkeit der Verteilung). Es kann nur eine Version der Archivhistorie verteilt werden. Wird festgestellt, dass ein signiertes Dat-Archiv von der signierten Kopie eines Peers abweicht, wird es als beschädigt behandelt, da der abweichende Inhalt auf einen gezielten Angriff des Dat-Autors hindeuten könnte. Es ist wichtig, dass alle Benutzer den gleichen Inhalt erhalten, und deshalb ist in Dat eine Integritätsprüfung eingebaut.

- Beaker Browser, Software sicher veröffentlichen

History log screenshotHistory log screenshot

Mit Hilfe der Beaker Web APIs können wir dieses Protokoll der Änderungen in unserem Archiv abfragen und anzeigen; dieses Protokoll zeigt sogar an, ob der Autor irgendwelche Journaleinträge gelöscht hat.

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

Mehr erfahren

Teilen Sie:

https://a.storyblok.com/f/270183/150x150/a3d03a85fd/placeholder.svg
Aaron BassettVonage Ehemalige

Aaron war ein Entwickler-Befürworter bei Nexmo. Aaron ist ein erfahrener Software-Ingenieur und Möchtegern-Digitalkünstler, der häufig Dinge mit Code oder Elektronik entwickelt, manchmal auch beides. Wenn er an etwas Neuem arbeitet, erkennt man das in der Regel am Geruch von brennenden Bauteilen in der Luft.