
Eu tenho um .mp4
arquivo de vídeo que veio de um arquivo não compactado .avi
capturado de uma webcam através do formato emgu
. O emgu videoWriter
está definido para que 30fps
até mesmo o vídeo real fps
seja possivelmente menor, por exemplo, 29fps
. O comando usado para compactar .avi
é:
Comando de compressão:
fmpeg -i uncompresedvideo.avi -v quiet -stats -nostdin -c:v libx264 -crf 1 -preset veryfast -maxrate 500k -bufsize 1835k vid.mp4
A saída de compressão de vídeo é:
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))
Além desta gravação de vídeo tenho um .wav
arquivo que veio de um dispositivo diferente. Estou tentando sincronizá-los com o conteúdo com o seguinte 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
A saída do comando de sincronização é:
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
Gostaria de mencionar que tanto o áudio quanto o vídeo têm início comum. Embora o conteúdo audiovisual tenha uma boa sincronização no início, a sincronização é perdida no final da gravação. Você poderia fazer uma sugestão sobre o que está acontecendo?
Sua ajuda é muito apreciada, obrigado.
Responder1
Acho que o problema é que seu vídeo de entrada já possui carimbos de data e hora errados devido à forma como foi codificado. Entendo que o vídeo original da webcam produzia quadros de comprimento variável (ou seja, um vídeo com taxa de quadros variável), mas um arquivo AVI descompactado só pode armazenar quadros deconstantecomprimento.
Assim, ao ler esse arquivo AVI (ou qualquer arquivo MP4 compactado posteriormente), o ffmpeg assumirá que é um vídeo com taxa de quadros constante. Isso leva ao "acumulo" de assincronicidade ao longo do tempo, uma vez que os carimbos de data e hora em seu AVI/MP4 têm deslocamentos constantes. O ffmpeg não pode corrigir isso para você, porque os carimbos de data e hora de entrada já estão incorretos. Em outras palavras, presumo que videoWriter
você se refere a criar um vídeo com taxa de quadros constante a partir de um vídeo com taxa de quadros variável, criando carimbos de data/hora incorretos. Sem saber quando ou como a taxa de quadros mudou, você não pode corrigir os carimbos de data/hora.
Sua única opção seria gerar novamente o stream de vídeo da webcam com um contêiner que suporte taxa de quadros variável (como MKV ou MP4/MOV). Então, qualquer conversão subsequente poderá sincronizar o conteúdo com um fluxo de áudio. Mas como o feed da webcam provavelmente está ao vivo, não há como voltar atrás. Além disso, também não acho que seja possível que o OpenCV videoWriter
produza uma taxa de quadros variável (mas não sou especialista nisso).
Observação: seria mais fácil corrigir esse problema se o vídeo original estivesse codificado com um código errado.constantetaxa de quadros. Você poderia então forçar o ffmpeg a assumir outra taxa de quadros para o vídeo de entrada, removendo efetivamente os carimbos de data e hora originais e gerando novos, assumindo uma taxa de quadros constante. Por exemplo, se a sua conversão de vídeo acabou criando um vídeo de 30 fps, mas a entrada original foi de 29 fps, faça o seguinte:
ffmpeg -r 29 -i <input> …