FFmpeg und HLS mehrere Audiowiedergaben

3407
Alfredo Di Napoli

Ich versuche, FFmpeg zu verwenden, um eine HLS-Wiedergabeliste zu erstellen, die mehrere Audiowiedergaben enthält, aber ich kann die Audio- und Videospuren nicht miteinander synchronisieren. Hier ist das Szenario:

  • Angenommen, ich habe 2 Videodateien mit jeweils 1 Audiospur
  • Ich verwende FFmpeg, um die beiden Videos zusammen zu verschieben, um ein einzelnes Video zu bilden. Beispiel:

FFmpeg und HLS mehrere Audiowiedergaben

  • Die extrahierte Audiospur für jede Datei (als .mp3 transkodiert)

  • Ich möchte eine HLS-Playlist erstellen, bei der die alternativen Audiospuren jeweils das linke und das rechte Audio sind:

FFmpeg und HLS mehrere Audiowiedergaben

Das Problem, das ich habe, ist, dass ich das Audio nicht richtig mit dem Video synchronisieren kann . Ich habe ein paar ffmpeg-Befehle ausprobiert, von denen jeder auf einer anderen Ebene naiv ist. Im besten Fall bekomme ich einen synchronisierten Stream auf dem Desktop, aber auf dem Handy (wo die Wiedergabe vom nativen Player des Geräts ausgeführt wird) Video verliert die Synchronisierung mit Audio sehr schnell, sobald ich zur anderen Videospur wechsle.

Ich verwende ffmpeg 3.1.1 .

Einen Beispielbefehl habe ich ausgehend von einem relativ einfachen Befehl ausprobiert, bei dem ich die Audiospuren dem segmenterMuxer und das Video den folgenden zuordnen hls:

ffmpeg -i dual.mp4 -i audio_left.mp3 -i audio_right.mp3 \ -threads 0 -muxdelay 0 -y \ -map 0 -pix_fmt yuv420p -vsync 1 -async 1 -vcodec libx264 -r 29.97 -g 60 -refs 3 -f hls -hls_time 10 -hls_list_size 0 video/index.m3u8 \ -map 1 -acodec aac -strict experimental -async 1 -ar 44100 -ab 96k -f segment -segment_time 10 -segment_list_size 0 -segment_list_flags -cache -segment_format aac -segment_list audio1/audio1.m3u8 audio1/audio1%d.aac \ -map 2 -acodec aac -strict experimental -async 1 -ar 44100 -ab 96k -f segment -segment_time 10 -segment_list_size 0 -segment_list_flags -cache -segment_format aac -segment_list audio2/audio2.m3u8 audio2/audio2%d.aac  

Um es komplexer zu machen, geben Sie den Rohcontainer aus mpegtsund schneiden Sie dann die Tracks auf:

ffmpeg -i dual_short.mp4 -i audio_left_short.mp3 -i audio_right_short.mp3 \ -threads 0 -muxdelay 0 -y \ -map 0:v -map 1 -map 2 -codec copy -pix_fmt yuv420p -vsync 1 -async 1 -shortest -f mpegts pipe:1 | ffmpeg-3.1.1 -i pipe:0 \ -map 0:0 -vcodec copy -r 29.97 -g 60 -refs 3 -bsf:v h264_mp4toannexb -f hls -hls_time 10 -hls_list_size 0 video/index.m3u8 \ -map 0:1 -f ssegment -segment_time 10 -segment_list_size 0 -segment_format aac -segment_list audio1/audio1.m3u8 audio1/audio1_%d.aac \ -map 0:2 -f ssegment -segment_time 10 -segment_list_size 0 -segment_format aac -segment_list audio2/audio2.m3u8 audio2/audio2_%d.aac 

Ich bin kein Audio- / Video-Experte. Ich bin mir ziemlich sicher, dass meine Argumentation etwas grundlegend fehlerhaft ist. Ich bitte Sie daher um Hilfe und Anleitung. Im Speziellen:

  • Ist das, was ich hier zu tun versuche, nicht machbar? Eine andere Möglichkeit, um es auszudrücken, besteht darin , N Audiospuren, die synchron mit dem Originalvideo aufgenommen wurden, zu erstellen, um eine HLS-Wiedergabeliste zu erstellen, bei der das Audio immer lippensynchron ist.
  • Ist das Video-FPS & Audio die Ursache des A / V-Synchronisationsproblems? Gibt es überhaupt einen Zusammenhang?
  • Hat die unterschiedliche Qualität des Videos (z. B. Bitrate) Auswirkungen auf die Synchronisierung?
  • Beeinflusst der von mir gewählte Ziel-Audio-Container (mp3 vs aac) die Synchronisierung?
  • Soll ich einen einzelnen Befehl mit mehreren Eingaben verwenden oder mit jedem Stream separat arbeiten?

Wie Sie sehen können, bin ich ziemlich verloren. Ich habe ausführlich über das Internet gesucht und Apple's "Effective HLS" von der WWDC 2012 aus gesehen. Die Informationen darüber, wie Sie effektive Multiple Audio Rendition-Wiedergabelisten erstellen, scheint jedoch im Internet knapp zu sein.

Danke für alle Hinweise.

3

1 Antwort auf die Frage

4
Alfredo Di Napoli

Ich habe die Lösung selbst gefunden.

Das Problem ist, dass der segmentMuxer einige Referenz-Frames betrachten muss, um das Audio richtig schneiden zu können, sodass das separate Mappen der Streams nicht funktioniert.

Was funktioniert, ist, ein "bulliges" .ts-Segment zu erzeugen, das alle Audio- und Videodateien enthält, und diese dann entsprechend zu schneiden. Ein einfaches und dennoch funktionierendes Beispiel:

ffmpeg-3.1.1 -i dual_short.mp4 -i audio_left_short.mp3 -i audio_right_short.mp3 \ -threads 0 -muxdelay 0 -y \ -map 0:v -map 1 -map 2 -pix_fmt yuv420p -movflags +faststart -r 29.97 -g 60 -refs 1 \ -vcodec libx264 -acodec aac -profile:v baseline -level 30 -ar 44100 -ab 64k -f mpegts out.ts  # Perform 3 passes: # 1. Generate the video. ffmpeg-3.1.1 -i out.ts -threads 0 -muxdelay 0 -y -map 0:v -vcodec copy -f hls -hls_time 10 -hls_list_size 0 video/index.m3u8 # Generate Audio 1 ffmpeg-3.1.1 -i out.ts -threads 0 -muxdelay 0 -y -map 0:a:0 -codec copy -f segment -segment_time 10 -segment_list_size 0 -segment_list audio1/audio1.m3u8 -segment_format mpegts audio1/audio1_%d.aac # Generate Audio 1 ffmpeg-3.1.1 -i out.ts -threads 0 -muxdelay 0 -y -map 0:a:1 -codec copy -f segment -segment_time 10 -segment_list_size 0 -segment_list audio2/audio2.m3u8 -segment_format mpegts audio2/audio2_%d.aac