
Tengo un .mp4
archivo de video que proviene de una .avi
captura sin comprimir de una cámara web a través de emgu
. El emgu videoWriter
está configurado para que 30fps
incluso el vídeo real fps
sea posiblemente más bajo, por ejemplo, 29fps
. El comando que se utiliza para comprimir .avi
es:
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 .wav
archivo 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 videoWriter
al 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 videoWriter
genere 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> …