El contenido audiovisual pierde sincronización

El contenido audiovisual pierde sincronización

Tengo un .mp4archivo de video que proviene de una .avicaptura sin comprimir de una cámara web a través de emgu. El emgu videoWriterestá configurado para que 30fpsincluso el vídeo real fpssea posiblemente más bajo, por ejemplo, 29fps. El comando que se utiliza para comprimir .avies:

Comando de compresión:

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

La salida de compresión de video es:

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

Además de esta grabación de video tengo un .wavarchivo que vino de un dispositivo diferente. Estoy intentando sincronizarlos con el contenido con el siguiente comando:

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

La salida del comando de sincronización es:

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

Me gustaría mencionar que tanto el audio como el video tienen un inicio común. Si bien el contenido audiovisual tiene buena sincronización al inicio, la sincronización se pierde al final del registro. ¿Podría por favor hacer una sugerencia sobre lo que está pasando?

Su ayuda es muy apreciada, gracias.

Respuesta1

Creo que el problema es que el vídeo de entrada ya tiene marcas de tiempo incorrectas debido a la forma en que fue codificado. Entiendo que el vídeo original de la cámara web generaba fotogramas de longitud variable (es decir, un vídeo con velocidad de fotogramas variable), pero un archivo AVI sin comprimir sólo puede almacenar fotogramas deconstantelongitud.

Por lo tanto, al leer ese archivo AVI (o cualquier archivo MP4 comprimido posteriormente), ffmpeg asumirá que es un video con velocidad de fotogramas constante. Esto lleva a que la asincronicidad se "acumule" con el tiempo, ya que las marcas de tiempo en su AVI/MP4 tienen compensaciones constantes. ffmpeg no puede solucionar este problema porque las marcas de tiempo de entrada ya son incorrectas. En otras palabras, supongo que el vídeo videoWriteral que te refieres creó un vídeo con velocidad de fotogramas constante a partir de uno con velocidad de fotogramas variable, creando marcas de tiempo incorrectas. Sin saber cuándo o cómo cambió esa velocidad de fotogramas, no se pueden corregir las marcas de tiempo.

Su única opción sería volver a generar la transmisión de video desde la cámara web con un contenedor que admita velocidad de fotogramas variable (como MKV o MP4/MOV). Luego, cualquier conversión posterior podría sincronizar el contenido con una transmisión de audio. Pero como la transmisión de la cámara web probablemente esté en vivo, no hay forma de regresar. Además, tampoco creo que sea posible que OpenCV videoWritergenere una velocidad de fotogramas variable (pero no soy un experto en esto).


Nota: Sería más fácil solucionar este problema si su video original estuviera codificado con un formato incorrecto.constantecuadros por segundo. Luego, podría forzar a ffmpeg a asumir otra velocidad de cuadros para el video de entrada, eliminando efectivamente las marcas de tiempo originales y generando otras nuevas, asumiendo una velocidad de cuadros constante. Por ejemplo, si tu conversión de video terminó creando un video de 30 fps, pero tu entrada original fue de 29 fps, haz esto:

ffmpeg -r 29 -i <input> …

información relacionada