FFmpeg dividir vídeo e mesclar de volta

8

Eu estou tentando usar FFmpeg para vídeo dividido com base em alguns start_timee end_timeinsumos, e substituir aqueles com outros arquivos de vídeo. Por exemplo, para entrada 10 15, precisarei substituir EXACT segundos 10 to 15por outro vídeo.

ESTÁ BEM. O que me vem à mente é o seguinte:

  1. Primeiro divida o vídeo (neste caso, 0-10, 10-15 e 15 final)
  2. Substitua o 10-15 pelo outro vídeo
  3. Mesclar todos os sub-vídeos de volta

Primeira pergunta: esta é a solução melhor e mais rápida? Temos um comando mais fácil ou outras ferramentas para substituir um período específico no vídeo por outro vídeo?

Segunda pergunta: Supondo que o FFmpeg seja a solução viável, quando eu simplesmente uso o comando ffmpeg -I input.video -ss 10 -t 5 -c copy output.mp4, meu código de processamento de vídeo não pode ler e processar o arquivo. Usei a mediainfoferramenta para comparar os dois arquivos e notei diferenças nos tamanhos dos cabeçalhos, enquanto todo o material relacionado ao codec de vídeo era o mesmo. Notei que o TAMANHO DO CABEÇOTE é diferente, o que aparentemente está causando o problema. Existe alguma maneira de forçar o tamanho do cabeçalho também (além dos codecs) ser o mesmo?

ATUALIZAÇÃO: Aqui está o .mp4arquivo original que funciona bem no emulador.

Ariana
fonte
Primeiro, teríamos que lidar com o problema que você mencionou na sua segunda pergunta. Por favor, mostre o comando exato que você está usando e a saída completa e sem cortes da linha de comando que você obtém do ffmpeg. Mostre também os erros reais que você recebe ao ler o arquivo - seria bom saber exatamente qual é o seu "código de processamento".
slhck
@slhck o código de processamento de vídeo é uma enorme base de código. Eu não posso compartilhar. É só que, por algumas razões, o arquivo original é lido, mas não o gerado novamente. No entanto, posso compartilhar o .mp4arquivo original, se necessário.
ArianaJul
Eu costumava mediainfo ferramenta para comparar os dois arquivos e diferenças aviso no tamanhos de cabeçalho e outras coisas
Ariana
Ter o original ajudaria, mas não seremos capazes de solucionar por que ele não pode ser lido, receio, se esse for algum código interno.
slhck
@slhck Enviei o arquivo. A minha pergunta é atualizada
Ariana

Respostas:

9

Usando trime concat- arquivos de origem com diferentes codecs

Para isso, verifique se seus arquivos individuais têm a mesma resolução e, idealmente, a mesma taxa de quadros e subamostragem de croma, etc. Isso evitará erros ou falhas durante a concatenação.

Você pode fazer tudo de uma só vez sem dividir o arquivo, usando os filtros trime concat:

ffmpeg -i edv_g24.mp4 -i short-video.mp4 -filter_complex "\
[0:v]trim=0:10,setpts=PTS-STARTPTS[v0]; \
[1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; \
[0:v]trim=15:30,setpts=PTS-STARTPTS[v2]; \
[v0][v1][v2]concat=n=3:v=1:a=0[out]" \
-map "[out]" output.mp4

Aqui, trimé usado para especificar as partes individuais dos fluxos de vídeo de entrada ( 0:v, 1:v) que você deseja concatenar mais tarde. Estas peças são nomeados v0através de v2. (O setptsfiltro redefine os carimbos de data e hora dessas partes individuais para 0, o que é necessário para a concatenação). Mais tarde, concatenamos as três partes.

Se você deseja cortar de um determinado registro de data e hora para o final, use em trim=start=15vez de especificar o intervalo.

Se seus arquivos tiverem áudio, você deverá aparar esses fluxos separadamente:

ffmpeg -i edv_g24_2.mp4 -i short-video.mp4 -filter_complex "\
[0:v]trim=0:10,setpts=PTS-STARTPTS[v0]; \
[0:a]atrim=0:10,asetpts=PTS-STARTPTS[a0]; \
[1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; \
[1:a]atrim=0:5,asetpts=PTS-STARTPTS[v1]; \
[0:v]trim=15:30,setpts=PTS-STARTPTS[v2]; \
[0:a]atrim=15:30,asetpts=PTS-STARTPTS[a2]; \
[v0][a0][v1][a1][v2][a2]concat=n=3:v=1:a=1[outv][outa]" \
-map "[outv]" -map "[outa]" output.mp4

Observe que vídeo e áudio serão recodificados neste caso - certifique-se de especificar metas de qualidade de saída apropriadas (por exemplo, -crfpara x264, x265 ou libvpx-vp9). Você pode ler mais sobre isso no Wiki do FFmpeg, por exemplo, para VP9 ou H.264 .

Usando segmentos individuais

Se você deseja dividir os clipes e montá-los posteriormente:

ffmpeg -i edv_g24.mp4 -ss 0 -to 10 -c copy part1.mp4
ffmpeg -i edv_g24.mp4 -ss 10 -to 15 -c copy part2.mp4
ffmpeg -i edv_g24.mp4 -ss 15 -c copy part3.mp4

ffmpeg -i part1.mp4 -i short-video.mp4 -i part3.mp4 -filter_complex \
"[0:v][1:v][2:v]concat=n=3:v=1:a=0[outv]" \
-map "[outv]" -t 30 output.mp4

Se os arquivos tiverem áudio, use a mesma abordagem acima:

ffmpeg -i part1.mp4 -i short-video.mp4 -i part3.mp4 -filter_complex \
"[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[outv][outa]" \
-map "[outv]" -map "[outa]" -t 30 output.mp4

Isso irá recodificar novamente o fluxo de vídeo. É um pouco mais direto, mas, caso contrário, deve ser equivalente ao método acima.

Usando o concatdesmuxer

Em princípio, você também pode tentar concatenar os fluxos de bits sem recodificá-los, usando o desmuxador concat. Crie um arquivo chamado concat.txte adicione as seguintes entradas (correspondentes aos videoclipes criados acima):

file 'part1.mp4'
file 'short-video.mp4'
file 'part3.mp4'

Em seguida, concatene esses arquivos individuais:

ffmpeg -f concat -i concat.txt -c copy output.avi

No entanto, isso exige que seus clipes tenham o mesmo codec, resolução, taxa de quadros etc. - para que não funcione com todos os tipos de fontes heterogêneas.

Usando concatprotocolo

O tipo acima de concatenação no nível de arquivo também pode ser alcançado usando o concatprotocolo, com o mesmo tipo de restrições acima (o mesmo codec, resolução etc.):

ffmpeg -i "concat:part1.avi|part2.avi|part3.avi" -c copy output.mp4

Para mais informações sobre concatenação, leia a respectiva página Wiki do FFmpeg .

slhck
fonte
Isso parece muito completo! Obrigado. Vou experimentá-los!
Ariana15
Idk por que usar o concatmétodo lança um erro:[concat @ 00000000025c2560] Line 1: unknown keyword 'part1.mp4 \\ text.txt: Invalid data found when processing input
Ariana
Para "usar segmentos individuais", vejo uma parada e um pequeno corte na saída. Existe alguma maneira de corrigir isso?
Ariana
O método 1 funciona perfeitamente. Uma coisa: como podemos especificar "até o final" sem indicar um número específico (em vez de 30 s)
Ariana
1
Desculpe, cometi um erro. Para o concatdesmuxador, a sintaxe era diferente. Corrigido agora. Para ir até o final, use trim=start=15, consulte a documentação do filtro de apara: ffmpeg.org/ffmpeg-filters.html#trim - quanto a problemas de tempo, isso realmente depende do material de origem. Ainda não houve problemas de concatenação com o clipe que você enviou.
slhck