Como usar o filtro ffmpeg overlay_cuda para fazer um vídeo SBS?
O FFMPEG há alguns meses lançou a nova versão do FFMPEG com o novo filtro "overlay_cuda", este filtro faz o mesmo que o "overlay", mas usando uma placa Nvidia para aplicá-lo.
Encontrei no site do FFMPEG a descrição do filtro, mas não há exemplos de como usá-lo. Os únicos exemplos que encontrei são de commits do desenvolvedor, mas são para colocar um vídeo ou uma foto sobre outro vídeo.
Eu antes do filtro de sobreposição normal fazia isso usando uma imagem nullsrc com o dobro da largura, mas agora não sei como fazer com esse filtro.
Descrição do compromisso: https://patchwork.ffmpeg.org/project/ffmpeg/patch/[email protected]/ página da web de documentação do ffmpeg: https://ffmpeg.org/ffmpeg-filters.html#overlay_005fcuda-1
Espero que você possa me ajudar.
Atualizar:
Fiz este pedido FFmpeg que:
- Insira cada vídeo.
- O primeiro vídeo cria preenchimento à direita e, em seguida, é carregado na memória do cartão.
- Com a sobreposição de Cuda, o outro vídeo coloca à direita do vídeo original.
ffmpeg -y -loglevel info \
-i $video_1 \ -hwaccel cuda -hwaccel_output_format cuda -i $video_2 \
-filter_complex \
" \
[0:v]pad=w=2*iw:h=ih:x=0:y=0,hwupload_cuda[base];
[base][1:v]overlay_cuda=x=800:y=0" \
-an -c:v h264_nvenc overlay_test.mp4
Mas recebo esta mensagem de erro:
[overlay_cuda @ 0x55fdec4b2ec0] Can't overlay nv12 on yuv420p
[Parsed_overlay_cuda_2 @ 0x55fdec4b2d80] Failed to configure output pad on Parsed_overlay_cuda_2
Error reinitializing filters!
Failed to inject frame into filter network: Invalid argument
Error while processing the decoded data for stream #1:0
Tenho problemas com os formatos de pixel, espero que você possa me ajudar.
Atualização 2:
Eu finalmente resolvi o problema do formato de pixel e agora faço a sobreposição com o preenchimento (adiciona espaço ao vídeo de sobreposição)
Este é o comando bem-sucedido:
ffmpeg -y -loglevel info \
-i $video_1 \ -hwaccel cuda -hwaccel_output_format cuda -i $video_2 \
-filter_complex \
" \
[0:v]pad=w=2*iw:h=ih:x=0:y=0,hwupload_cuda,scale_npp=format=nv12[base];
[base][1:v]overlay_cuda=x=800:y=0" \
-an -c:v h264_nvenc overlay_test.mp4
Agora eu quero mudar x=800para uma variável como, x=iw+1mas parece que este filtro não suporta isso. Existe uma maneira de definir uma variável global?
Respostas
Deixa comigo! Depois de ler novamente o que posso fazer com os filtros Cuda, descobri que scale_nppnão só redimensiona os vídeos, mas também pode alterar o formato dos pixels.
Então, depois de alguns testes, encontrei uma solução muito boa:
ffmpeg -y -loglevel info \
-hwaccel cuda -hwaccel_output_format cuda -i $video_1 \ -hwaccel cuda -hwaccel_output_format cuda -i $video_2 \
-filter_complex \
" \
[0:v]scale_npp=640:-2:format=yuv420p,hwdownload,pad=w=2*iw:h=ih:x=0:y=0,hwupload_cuda,scale_npp=format=nv12[base];
[1:v]scale_npp=640:-2:format=nv12[overlay_video];
[base][overlay_video]overlay_cuda=x=640:y=0" \
-an -c:v h264_nvenc overlay_test.mp4
O que torna este comando FFMPEG:
- Insira dois vídeos com decodificação Cuda.
- O primeiro vídeo
[0:v]:- Escale para 640 pixels de largura mantendo o rádio de aspecto com um formato de pixel YUV420P
- Baixe da memória da GPU para a memória do sistema
- Aplique um filtro de preenchimento para adicionar 640 pixels de largura à direita do vídeo
- Faça upload novamente para a memória da GPU
- Mude o formato do pixel para nv12
- Rotular como
[base]
- O segundo video
[1:v]- Escale para 640 pixels de largura mantendo o rádio de aspecto com um formato de pixel NV12
- Rotular como
[overlay_video]
- Aplicar
overlay_cudafiltro[base]vídeo como vídeo de fundo[overlay_video]vídeo como o vídeo em primeiro plano- Insira
[overlay_video]640 pixels à direita do[base]vídeo
- Termine a codificação
-ancomo áudio nulo (isso pode ser excluído, no uso real você precisa misturar os sinais de áudio ou escolher um dos dois vídeos, ou mesmo adicionar uma fonte de áudio externa).-c:v h264_nvencCodifique o vídeo usando a GPU com o codec h264 (aqui você pode mudar de acordo com suas necessidades).
A única desvantagem é que você precisa definir uma resolução de antemão, não há como definir a resolução de entrada (como no filtro de sobreposição normal). Felizmente, você pode fazer isso como uma variável para um script e usar ffprobepara obter essa variável antes.