Audiovisuelle Inhalte verlieren die Synchronisierung

Audiovisuelle Inhalte verlieren die Synchronisierung

Ich habe eine .mp4Videodatei, die aus einer unkomprimierten .aviAufnahme einer Webcam über stammt emgu. Der emgu videoWriterist so eingestellt, dass 30fpssogar das echte Video fpsmöglicherweise kleiner ist, z. B. 29fps. Der Befehl, der zum Komprimieren verwendet wird, .avilautet:

Komprimierungsbefehl:

fmpeg -i uncompresedvideo.avi -v quiet -stats -nostdin -c:v libx264 -crf 1 -preset veryfast -maxrate 500k -bufsize 1835k vid.mp4

Die Videokomprimierungsausgabe ist:

ffmpeg version N-82060-g0cfd6cc Copyright (c) 2000-2016 the FFmpeg developers
  built with gcc 5.4.0 (GCC)
  configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-dxva2 --enable-libmfx --enable-nvenc --enable-avisynth --enable-bzlib --enable-libebur128 --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenh264 --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --enable-lzma --enable-decklink --enable-zlib
  libavutil      55. 32.100 / 55. 32.100
  libavcodec     57. 63.103 / 57. 63.103
  libavformat    57. 52.100 / 57. 52.100
  libavdevice    57.  0.102 / 57.  0.102
  libavfilter     6. 64.100 /  6. 64.100
  libswscale      4.  1.100 /  4.  1.100
  libswresample   2.  2.100 /  2.  2.100
  libpostproc    54.  0.100 / 54.  0.100
Input #0, avi, from 'C:\....\uncompresedvideo.avi':
  Metadata:
    encoder         : Lavf56.36.100
  Duration: 00:02:50.27, start: 0.000000, bitrate: 110597 kb/s
    Stream #0:0: Video: rawvideo (I420 / 0x30323449), yuv420p, 640x480, 110613 kb/s, 30 fps, 30 tbr, 30 tbn, 30 tbc
[libx264 @ 0000000002636460] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 AVX2 LZCNT BMI2
[libx264 @ 0000000002636460] profile High, level 3.0
[libx264 @ 0000000002636460] 264 - core 148 r2721 72d53ab - H.264/MPEG-4 AVC codec - Copyleft 2003-2016 - http://www.videolan.org/x264.html - options: cabac=1 ref=1 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=2 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=16 chroma_me=1 trellis=0 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=0 threads=6 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=1 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=10 rc=crf mbtree=1 crf=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 vbv_maxrate=500 vbv_bufsize=1835 crf_max=0.0 nal_hrd=none filler=0 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to 'C:\....\vid.mp4':
  Metadata:
    encoder         : Lavf57.52.100
    Stream #0:0: Video: h264 (libx264) ([33][0][0][0] / 0x0021), yuv420p, 640x480, q=-1--1, 30 fps, 15360 tbn, 30 tbc
    Metadata:
      encoder         : Lavc57.63.103 libx264
    Side data:
      cpb: bitrate max/min/avg: 500000/0/0 buffer size: 1835000 vbv_delay: -1
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (libx264))  

Zusätzlich zu dieser Videoaufzeichnung habe ich noch eine .wavDatei, die von einem anderen Gerät stammt. Diese versuche ich mit folgendem Befehl inhaltlich zu synchronisieren:

ffmpeg.exe -i vid.mp4 -r 30 -i audio.wav -ar 16000 -map 0:0 -map 1:0 -vcodec copy -acodec aac -shortest output.mp4

Die Ausgabe des Synchronisierungsbefehls lautet:

ffmpeg version N-82060-g0cfd6cc Copyright (c) 2000-2016 the FFmpeg developers
  built with gcc 5.4.0 (GCC)
  configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-dxva2 --enable-libmfx --enable-nvenc --enable-avisynth --enable-bzlib --enable-libebur128 --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenh264 --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --enable-lzma --enable-decklink --enable-zlib
  libavutil      55. 32.100 / 55. 32.100
  libavcodec     57. 63.103 / 57. 63.103
  libavformat    57. 52.100 / 57. 52.100
  libavdevice    57.  0.102 / 57.  0.102
  libavfilter     6. 64.100 /  6. 64.100
  libswscale      4.  1.100 /  4.  1.100
  libswresample   2.  2.100 /  2.  2.100
  libpostproc    54.  0.100 / 54.  0.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'audio.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf57.52.100
  Duration: 00:02:50.27, start: 0.000000, bitrate: 507 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 640x480, 504 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
    Metadata:
      handler_name    : VideoHandler
Guessed Channel Layout for Input Stream #1.0 : mono
Input #1, wav, from 'audio.wav':
  Duration: 00:02:52.29, bitrate: 512 kb/s
    Stream #1:0: Audio: pcm_f32le ([3][0][0][0] / 0x0003), 16000 Hz, mono, flt, 512 kb/s
Output #0, mp4, to 'output.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf57.52.100
    Stream #0:0(und): Video: h264 (High) ([33][0][0][0] / 0x0021), yuv420p, 640x480, q=2-31, 504 kb/s, 30 fps, 30 tbr, 15360 tbn, 15360 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1: Audio: aac (LC) ([64][0][0][0] / 0x0040), 16000 Hz, mono, fltp, 69 kb/s
    Metadata:
      encoder         : Lavc57.63.103 aac
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #1:0 -> #0:1 (pcm_f32le (native) -> aac (native))
Press [q] to stop, [?] for help
frame= 5108 fps=1316 q=-1.0 Lsize=   11735kB time=00:02:52.28 bitrate= 558.0kbits/s speed=44.4x
video:10486kB audio:1151kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.836344%
[aac @ 00000000026977c0] Qavg: 65093.531

Ich möchte darauf hinweisen, dass Audio und Video einen gemeinsamen Anfang haben. Während der audiovisuelle Inhalt am Anfang gut synchronisiert ist, geht die Synchronisation am Ende der Aufnahme verloren. Können Sie bitte einen Vorschlag machen, was da passiert?

Wir wissen Ihre Hilfe sehr zu schätzen, danke.

Antwort1

Ich denke, das Problem ist, dass Ihr Eingabevideo aufgrund der Art und Weise, wie es codiert wurde, bereits falsche Zeitstempel hat. Ich verstehe, dass das ursprüngliche Webcam-Video Frames mit variabler Länge ausgab (d. h. ein Video mit variabler Bildrate), aber eine unkomprimierte AVI-Datei kann nur Frames vonKonstanteLänge.

Beim Lesen dieser AVI-Datei (oder einer später komprimierten MP4-Datei) geht ffmpeg daher davon aus, dass es sich um ein Video mit konstanter Bildrate handelt. Dies führt dazu, dass sich im Laufe der Zeit Asynchronität „aufbaut“, da die Zeitstempel in Ihrem AVI/MP4 konstante Offsets aufweisen. ffmpeg kann dies nicht für Sie beheben, da die Eingabezeitstempel bereits falsch sind. Mit anderen Worten gehe ich davon aus, dass das von videoWriterIhnen erwähnte Video aus einem Video mit variabler Bildrate ein Video mit konstanter Bildrate erstellt hat, wodurch falsche Zeitstempel erstellt wurden. Ohne zu wissen, wann oder wie sich diese Bildrate geändert hat, können Sie die Zeitstempel nicht korrigieren.

Ihre einzige Möglichkeit wäre, den Videostream von der Webcam mit einem Container neu zu generieren, der variable Bildraten unterstützt (wie MKV oder MP4/MOV). Dann könnte jede nachfolgende Konvertierung den Inhalt mit einem Audiostream synchronisieren. Da dieser Webcam-Feed aber wahrscheinlich live ist, gibt es keine Möglichkeit, zurückzugehen. Außerdem glaube ich nicht, dass es für OpenCVs möglich ist, videoWritervariable Bildraten auszugeben (aber ich bin kein Experte auf diesem Gebiet).


Hinweis: Dieses Problem lässt sich leichter beheben, wenn Ihr Originalvideo mit einem falschenKonstanteBildrate. Sie könnten dann ffmpeg zwingen, eine andere Bildrate für das Eingabevideo anzunehmen, wodurch die ursprünglichen Zeitstempel effektiv entfernt und neue generiert werden, wobei eine konstante Bildrate angenommen wird. Wenn Ihre Videokonvertierung beispielsweise ein 30-fps-Video erstellt hat, Ihre ursprüngliche Eingabe jedoch 29 fps betrug, gehen Sie wie folgt vor:

ffmpeg -r 29 -i <input> …

verwandte Informationen