Skript für Ansagen in mp3-Dateien

Ich habe mir mit dem Programm „mp3 diags“ die resultierenden Dateien angeschaut und festgestellt, dass sie vermutlich auf ungeeignete Weise zusammengefügt werden. Zumindest mein DFPlayer kommt mit mehreren mp3 Streams innerhalb einer mp3 Datei anscheinend nicht klar.

Das Problem ist der Aufruf von ffmpeg, was in diesem Fall auf Dateiebene arbeitet. Das heißt, dass die mp3s einfach hintereinander weg aneinander gehangen werden, siehe auch hier: https://trac.ffmpeg.org/wiki/Concatenate
Besser wäre es vermutlich, den „demuxer“ und nicht das „protocol“ zu benutzen.

Bei alldem ist mir außerdem noch aufgefallen, dass die Metadaten anscheinend beim Hinzufügen der Ansagen „verschwinden“. Sie sind nicht wirklich weg, aber jeder normale Player liest wohl nur die erstbesten Metadaten, die er findet. Leider sind die in diesem Fall „richtigen“ Metadaten in der zweiten Datei innerhalb der mp3 versteckt. Auch das ist wohl ffmpeg geschuldet. Man müsste hier denke ich lediglich nach dem concat Parameter noch zusätzlich erst „-i“ und dann nochmal den Namen der zweiten Datei hinzufügen. Dann könnte auch das Mapping der Metadaten korrekt funktionieren.

Ich habe meine Dateien jetzt erstmal mittels „foobar2000“ und der Funktion „rebuild mp3 stream“ repariert und bisher sieht das gut aus. Genau weiß ich leider nicht was da passiert, aber so wie es hinterher in „mp3 diags“ aussieht, werden alle ungültigen Metadaten usw verworfen und die mp3 Streams so zusammengefügt, dass der DFPlayer damit glücklich ist und nichts mehr abgeschnitten wird. Die Metadaten sind zwar weg, aber die braucht man ja nicht zwingend.

Ich fasse nur nochmal meine Beobachtungen zusammen, um den aktuellen Stand bzw. die Probleme in die ich gelaufen bin zu dokumentieren:

  • Zumindest unter Windows akzeptiert das subprocess Modul kein byte Objekt als Parameter. Ich habe da das Encoding des json body einfach weglassen. Geschickter wäre sicher die Abhängigkeit zu curl loszuwerden wie @Til anfangs schon geschrieben hat.
  • Der Aufruf von ffmpeg zum Zusammenfügen der mp3s ist anscheinend problematisch. Möglicherweise kann man den „concat demuxer“ verwenden, so dass die mp3 Streams und nicht die Dateien zusammengefügt werden.
  • Die Metadaten gehen beim Hinzufügen der Ansagen verloren. Hier könnte beim Aufruf von ffmpeg ein zusätzlicher „-i“ Parameter (mit dem Namen der Datei die die korrekten Metadaten enthält) Abhilfe schaffen.

Ich habe momentan leider weder die Zeit den Code anzupassen, noch das Ganze auf verschiedenen Systemen auch vernünftig zu testen. Wie dem auch sei: Vielleicht hilft es ja dem ein oder anderen oder jemand fühlt sich berufen da weiter zu machen :slightly_smiling_face:

Vielen Dank @Dave für Deine Analyse.

Hier noch meine Einschätzung zu den Punkten:

  • Das Weglassen des Encodings hört sich für mich gefährlich an. Wenn es bei Dir nun tut, dann ist ja gut. Aber ich sehe die Gefahr, dass es auf anderen Plattformen (mit z.B. anderem Default-Encoding) Probleme machen könnte. Ich denke genau wie Du, dass das Ganze am besten zu lösen wäre, wenn man einfach curl los wird.
  • In der Version, die ich in Stephans Fork contributed habe, wird bei der Ansage zumindest Sample-Rate und Mono/Stereo an die Quell-Datei angepasst. Damit funktioniert es bei mir wunderbar auf dem DFPlayer. Mich wundert etwas, dass es bei Dir nicht so ist. Aber OK - auch vom DFPlayer gibt es ja verschiedene Versionen. Wenn die mp3 aber tatsächlich nur aus einem Stream bestünde, wäre es natürlich noch sauberer. Allerdings sollte unbedingt vermieden werden, dass die Quell-Datei neu codiert wird - aktuell funktioniert es ja ohne Qualitätsverlust.
  • Der Verlust der Metadaten stört mich persönlich nicht. Für den Anwendungsfall braucht man diese ja nicht.
1 „Gefällt mir“

Hallo alle zusammen, entweder ich finde es nicht oder es gibt noch keine Anleitung für den Mac zum nutzen dieses Scriptes. Kann mir da jemand etwas Unterstützung geben?

DANKE

Das erste posting in diesem thread enthalt doch die Anleitung. Was Ähnliches findest du auch in der readme in meinem Fork.

2 „Gefällt mir“

Ach sorry ja klar… ich meine wie ich es mit dem say Befehl nutze…

Du ersetzt einfach den google Parameter mit --use-say. Steht auch so dokumentiert…

Oh man :see_no_evil: wer lesen kann ist klar im Vorteil… DANKE fürs wecken :rofl:

Hallo zusammen,
mir haben die Toolboxen mpgtx (gibt es zumindest für Linux und Windows, aber etwas angestaubt und kommt wohl nicht mit allen mp3-Dateien klar) und mp3cut+mp3cue (kennt die Paketverwaltung von meinem Debian, mp3cut kann laut Anleitung auch zusammenfügen) geholfen. Beide encoden nicht neu, sondern schneiden eben nur an „Block-Grenzen“ (bei Videos würde man I-Frames sagen, bei mp3 kenne ich die korrekte Bezeichnung nicht).
Viele Grüße!

Ich habe zu danken. Dein Skript ist für diesen speziellen Anwendungsfall einfach grandios und hat mir und sicher vielen anderen enorm weiter geholfen. Die Zeit das Ganze unter Windows zum Laufen zu bekommen und zu verstehen war es mir auf jeden Fall Wert.

  • Bezüglich des Encodings stimme ich dir voll und ganz zu. Eine universelle, OS-unabhängige Lösung wäre natürlich großartig. Anbieten würde es sich „urllib.requests“ bzw. „http.client“ aus der Python Standard Library statt curl zu benutzen. Natürlich gibt es auch „requests“, allerdings müsste das über pip nachinstalliert werden, was je nach System erfahrungsgemäß auch gern mal nicht ohne Weiteres funktioniert und so eine weitere Hürde für technisch weniger versierte Nutzer darstellen könnte.
  • Das Problem mit den abgeschnittenen Titelanfängen wurde hier ja schon einige Male genannt. Ich halte es auch für wahrscheinlich, dass manche Player mit nicht standardkonformen MP3s eben so ihre Probleme haben. Ich habe testweise mal den Concat demuxer von ffmpeg im Skript eingebaut und dabei festgestellt, dass der nicht wie ich angenommen hatte aus 2 Streams einen macht. In der Zieldatei sind hinterher zwar weniger überflüssige / doppelte Header bzw. Metadaten, aber es sind trotzdem 2 getrennte Audio Streams (auch hier ohne Qualitätsverlust). Das Abspielen auf einem DFPlayer konnte ich bisher leider noch nicht testen.
  • Auf die Metadaten kann ich auch verzichten. Es ist mir nur aufgefallen; Berufskrankheit :wink:

Falls jemand ganz mutig ist:


Ein erster Versuch die Python Skripte zu modifizieren, um die o.g. Probleme zu beseitigen. Es war erstaunlich einfach umzusetzen und meine ersten Tests sahen vielversprechend aus.

  • Sollte jetzt zumindest mit Google TTS auch direkt unter Windows laufen (bisher ungetestet).
  • Curl wird nicht mehr gebraucht.
  • Der Concat demuxer von ffmpeg wird benutzt, damit korrekte MP3 Header geschrieben werden und so einige DFPlayer (hoffentlich) weniger Probleme beim Abspielen machen.
  • Die Metadaten werden von der Quell- zur Zieldatei kopiert.

Beim Aufbau der nächsten Box werde ich die Skripte sicher auch nochmal brauchen und dann ausgiebig testen, aber falls jemand bis dahin schonmal Zeit und Lust hat was auszuprobieren oder anzupassen: Nur zu :slight_smile:

1 „Gefällt mir“

Ich habe gesehen, dass @Peer hier ein Beispiel gepostet hat, wie man über notevibes.com Texte mittels Python erzeugen kann. Das tolle ist, dass man da keinen Account braucht und Notevibes auch die Google TTS Stimmen benutzt. Als ich das testweise eingebaut hatte fiel mir auf, dass das nicht mehr funktioniert, weil auf der Seite jetzt anscheinend reCaptcha eingebaut ist :frowning:

Merkwürdig. Ich habe notevibes.com gerade ausprobiert und es läuft wie vorher ohne Captchas…

Das ist in der Tat sehr merkwürdig. Vielleicht haben die das im Testbetrieb für eine begrenzte Anzahl User laufen und es wird nach und nach erweitert. Alternativ könnte es natürlich auch sein, dass mir da ein Fehler unterlaufen ist. Es ist auch nicht so, dass ich ein Captcha eingeben muss, aber in den dev tools im Browser sehe ich, dass reCaptcha da ist und der Browser beim POST einen Parameter dafür im Payload mitschickt. Mit Python bekomme ich bei einem POST zwar die Seite zurück, aber keinen Link zur mp3 wie es eigentlich sein sollte. Danke auf jeden Fall für die Info. Ich schau mir das wohl doch nochmal genauer an :slightly_smiling_face:

Hmm, nun habe ich das auch genau so wie von Dir beschrieben. Damit funktioniert das Python-Script leider nicht mehr. Durch Recaptcha ist der Inhalt nicht mehr so einfach aus der POST-Request-Antwort extrahierbar. Evtl. könnte man auf das Wettrüsten einsteigen und mit dem Python-Anticaptcha-Tool die Recaptchas lösen lassen, aber mir fehlt derzeit die Zeit, das anzugehen…

Ich bin jetzt dazu gekommen das nochmal komplett durchzuspielen: Unter Ubuntu 18.04 und Windows 10 lief das angepasste Skript problemlos durch. Ich habe mehrere Ansagen für verschiedene Quelldateien erstellt und anscheinend ist der DFPlayer jetzt glücklich mit den mp3s. Zumindest habe ich keine abgeschnittenen Titelanfänge mehr feststellen können :slightly_smiling_face:
Ich werde noch einen Schwung Ansagen erstellen / prüfen und bei Gelegenheit einen PR erstellen.

Edit: Pull Request im Fork von @stephan. Danke nochmal für die Unterstützung :slightly_smiling_face:

Guten Tag,

ich habe nach der Anleitung oben die Dateien mit einer Ansage zu versehen. Leider bekomme ich immer diese Fehlermeldung:

c:\Python>python add_lead_in_messages.py -i C:\test -o C:\test\test --use-google-key=XXXX
Adding lead-in "" to C:\test\test\50.mp3

Generating: temp-lead-in.mp3 -
HTTP Error 403: Forbidden
Traceback (most recent call last):
     File "add_lead_in_messages.py", line 135, in <module>
    addLeadInMessage(args.input, args.output)
  File "add_lead_in_messages.py", line 55, in addLeadInMessage
    addLeadInMessage(os.path.join(inputPath, child), os.path.join(outputPath, child))
  File "add_lead_in_messages.py", line 84, in addLeadInMessage
    text_to_speech.textToSpeechUsingArgs(text=text, targetFile=tempLeadInFile, args=args)
  File "c:\Python\text_to_speech.py", line 64, in textToSpeechUsingArgs
    textToSpeech(text, targetFile, lang=args.lang, useAmazon=args.use_amazon, useGoogleKey=args.use_google_key)
  File "c:\Python\text_to_speech.py", line 90, in textToSpeech
    mp3Data = base64.b64decode(responseJson['audioContent'])
TypeError: 'NoneType' object is not subscriptable

Ist dieser Fehler bekannt? Wäre super wenn ihr mir helfen könntet.

Liebe Grüße Max

edit: Ich glaube es liegt daran, das ich das " Cloud Text-to-Speech API" nicht aktiviert habe. Wenn ich das aber aktivieren will, muss ich ein Bankkonto hinterlegen, was ich aber eigentlich nicht machen möchte. Gibt es da eine andere Lösung?

Naja. Ohne aktivierte Api geht es leider nicht. Für Amazon Polly bräuchtest du auch einen Account, also fällt das vermutlich ebenso raus.

Die beiden Engines klingen aber mit Abstand am besten und wenn du vor etwas Aufwand nicht zurück schreckst, könntest das ganze auch händisch machen wie es hier schonmal vorgeschlagen wurde:

Dann müsstest du die einzelnen mp3s hinterher nur z.B. mit Hilfe von ffmpeg (command line) oder mit einem anderen geeigneten Tool (z.B. xrecode3) zusammenfügen.

Zum händischen Nutzen von Google TTS: Google hat bei der Sprachausgabe des Translators inzwischen eingebaut, dass die Ausgaben mit wechselnden Geschwindigkeiten erfolgen. Ein und derselbe Text mehrmals hintereinander „vorgelesen“ klingt also unterschiedlich. Damit ist der händische Weg leider komplizierter geworden, da man jeden Text ggf. mehrmals vorlesen lassen muss, bis alles passt. :face_with_raised_eyebrow:

1 „Gefällt mir“

Das ist ja frech. Es gibt ja aber noch mehr Möglichkeiten:


Da kommt man mit den dev Tools des Browsers sicher auch irgendwie ran.

Wo ist das Problem für einen Service den man in Anspruch nimmt auch zu bezahlen? Abgesehen davon, laut Preisliste von Google sind je nach Stimme bis 1-4 Millionen Zeichen pro Monat kostenlos. Also damit sollte man doch hinkommen…