[ TAG 67 ][27.06.2021] - Erfolgreich - [PHASE-0]-Neues Arbeitspaket
Es ist [27.10.2021][1010] - Ich beginne meine Worksession. Das letzte Modul befasste sich mit der Aufnahme von Audio-Streams. Ich muss mich noch etwas genauer in [pydub] einarbeiten. Um Entscheidungen zu treffen muss ich erst die [ PHASE-0 ] durchlaufen. Ich verschaffe mir einen Überblick über die Funktionen und Arbeitsweisen der Library. [pydub] benutzt [ ffmpeg ].
- Quelle
- [ http://pydub.com/ ]
- [ https://github.com/jiaaro/pydub/blob/master/API.markdown ]
- [ https://raw.githubusercontent.com/jiaaro/pydub/master/API.markdown ]
- [ https://www.youtube.com/watch?v=4E7N7W1lUkU ]
- [ https://www.youtube.com/watch?v=CMj9158aVK8 ]
- Installiere ffmpeg
- [ https://www.youtube.com/watch?v=MPV7JXTWPWI&list=RDCMUCTCvWvqjktIq0uvM3trAHCg&index=1 ]
- [ https://www.youtube.com/watch?v=M58rc7cxl_s&list=RDCMUCTCvWvqjktIq0uvM3trAHCg&index=2 ]
- [ https://www.youtube.com/watch?v=hElDsyuAQDA&list=RDCMUCTCvWvqjktIq0uvM3trAHCg&index=3 ]
- [ https://www.youtube.com/results?search_query=python+wav+to+mp3 ]
Das erste Problem besteht darin, dass ich bei Aufnahme ein [numpy]-Array. Es sind "rohe" unkomprimierte Daten. Eine [mp3]-Datei erwartet komprimierte daten. Somit müssen die gewonnen Daten aus [numpy]-Array komprimiert werden. Ich weiß jetzt nicht ob man in eine mp3-Datei segmentierte Daten hineinspeichern kann.
Ich habe die API-Dokumentation von [pydub] durchgearbeitet. Dabei habe ich eine Funktion gefunden, die für das direkte hineinschreiben von Audiosignalen in [mp3] nützlich sein könne. Es gibt jedoch ein kleines Problem, ich weiß nicht wie groß ein python-Array sein darf. Dieser Punkt hängt von vielen Faktoren ab. Einer der einfachsten davon ist die RAM-Speicher-Größe. Unabhängig davon halte ich es für absolut nicht Sinnvoll alle Sample-Daten im RAM-Speicher zu lassen. Das ist der Grund warum ich Module eingeführt habe, in denen ich mich mit STREAM beschäftigt habe.
Im Modul [IAP-20210601-20210623-1100] habe ich die Anzahl der Elemente bzw. Frames im [numpy]-Array gemessen, die an die Call-Back-Methode übergeben wurden. Die Anzahl der Frames blieb zu meinen Erstaunen immer gleich. Ich habe kein Block definiert. Wie dem auch sei, es waren immer [1136 Frames].
Wenn ich mir die [WAV-SPEZIFIKATIONEN-20210622-1255] und [WAV-SPEZIFIKATIONEN-20210625-1200] nehme, so entsprechen [1136 Frames] => [9.088 Bytes] => [25,75 Millisekunden]. Im vergleich zu den modernen RAM-Speicher sind es sehr winzige Datenpakete.
- [ 1136 Frames ] = [4Bytes] x [ 2 Channels ] x [ 1136 Frames ] = [ 9.088 Byte] = [ 9 kB ]
- 9 kB an Sample-Daten wurden immer Stückchenweise übergeben und in die Datei hineingeschrieben.
- Mein System hat ein 64 Bit Prozessor (für Adressierungen) und 16 GB - RAM
- Mit 9 kB werde ich garantiert nicht an die grenzen kommen. Aber wenn ich nicht aufpasse könnte ich Anwendung sehr langsam machen.
- [ 44100 Hz ] = [44100 Frames/Sekunde] entspricht [ 2,27 x10^(-5) Sekunden/Frame]
- [ 2,27 x10^(-5) Sekunden/Frame] x [ 1136 Frames ] = [ 0,02575 Sekunden ]
- [ 0,02575 Sekunden ] = [ 25,75 Millisekunden ]
- Wie groß kann ein python-Array werden?
- https://stackoverflow.com/questions/855191/how-big-can-a-python-list-get
Es gibt etwas, was mir an der [ AudioSegment(...).get_array_of_samples() ] nicht gefällt. Oder ich halte es für meinen Zweck nicht sehr sinnvoll. Auf der Seite 10 meines Ausdruckes wird ein Codebeispiel gegeben, wie [numpy]-Arrays in [AudioSegmente] konvertiert werden können.
Es wird die Methode [scipy.io.wavfile.write(wav_io,16000,fp_arr)] benutzt. Diese Methode habe ich im Modul [IAP-20210601-20210609-2325] benutzt. Die [write(...)]-Methode von [scipy] eröffnet automatisch einen File-Stream und schließt den auch automatisch. Das lässt mich vermuten, dass jedes mal wenn ich die [write(...)]-Methode ausführe, bekomme ich ein WAV-Header generiert. Ich bekomme jedesmal eine mini-Wave-Datei mit 25,75 Millisekunden generiert, die dann in [mp3] umgewandelt wird. Das halte ich für keine gute Lösung. Bei einer Aufnahme von einer Minute, müsste ich 2400 mal eine WAV mit Header generieren, in [mp3] konvertieren und wieder löschen. Bei nur einer Minute werden wir [ 211 kB ] Datenmüll produzieren, das wir gar nicht brauchen und gar nicht nutzen.
Da ich zu diesen Zeitpunkt nicht die internen Abläufe der Methode [pydub.AudioSegment.from_wav(...)] kenne, halte ich die Vorgehensweise den Stream direkt in mp3 zu konvertieren doch für nicht sehr gut. Wesentlich Sauberer wäre es, wenn ich eine RAW-Datei oder WAV-Datei generieren würde. Wenn die Aufnahme beendet wurde, wird dann die Aufgezeichnete WAV-Datei in MP3-Umgewandelt. In [pydub] wird dieser Vorgang intern von [ ffmpeg ] erledigt.
- [ 60 Sekunden ] / [ 0,025 Sekunden ] = 2400 WAV-Files
- 88 Bytes pro Header mit RIFF und PEAK-Chunk
- [ 2400 WAV-Files mit Header ] x [ 88 Bytes pro Header ] = [ 211.200 Bytes Header Gesamt]
- [ 211.200 Bytes Header Gesamt] = 211 kB
- Quelle:
Zurzeit sieht für mich die Lösung erst WAV-Files zu erstellen und danach komprimieren am besten aus. Diese winzigen Datenstücke ständig zu komprimieren und zu einer [mp3] hinzufügen, halte ich nicht für sinnvoll. Eine bessere Lösung wäre, die gesammelten InputDaten in eine unkomprimierte Datei zusammen zu fassen. Diese Sammeldatei könnte man dann, nach dem Beenden der Aufnahme komprimieren. Der Komprimierungsvorgang könnte dann in einen separaten Prozess oder Thread laufen.
Kommentare
Kommentar veröffentlichen