Cortando os vídeos com base no horário de início e término usando ffmpeg

512

Tentei cortar o vídeo usando o horário de início e término do vídeo usando o seguinte comando

ffmpeg -ss 00:00:03 -t 00:00:08 -i movie.mp4 -acodec copy -vcodec copy -async 1 cut.mp4

Usando o comando acima, eu quero cortar o vídeo de 00:00:03para 00:00:08. Mas não está cortando o vídeo entre esses momentos, em vez de cortá-lo nos primeiros 11 segundos. alguém pode me ajudar como resolver isso?

Editar 1:

Eu tentei cortar usando o seguinte comando, sugerido por mark4o

ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4

Mas foi mostrado o seguinte erro.

o codificador 'aac' é experimental, mas codecs experimentais não estão ativados

então eu adicionei o -strict -2no comando ou seja,

ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 -strict -2 cut.mp4

Agora está funcionando bem.

Kalai
fonte
3
Sua saída do console ffmpeg completa e sem cortes está ausente. Sempre inclua isso ao perguntar. Obrigado.
slhck
3
De onde você conseguiu -strict 2? Apenas curioso, uma vez que não é nos docs: ffmpeg.org/ffmpeg.html
StackOverflowed
Sua para a qualidade após a instalação ffmpeg, Em ffmpeg ajuda que você pode encontrar esta opção
Kalai
1
superuser.com/questions/138331/using-ffmpeg-to-cut-up-video
Ciro Santilli郝海东冠状病六四事件法轮功
1
Eu acho que o problema aqui foi, na verdade, apenas o fato de você colocar o de e para ANTES do -i movie.mp4. Os argumentos para esse fluxo vão DEPOIS, certo? É por isso que a outra maneira funcionou. = /
Brent Rittenhouse

Respostas:

575

Você provavelmente não possui um quadro-chave na marca de 3 segundos. Como os quadros-chave que não codificam diferenças de outros quadros, eles exigem todos os dados que começam com o quadro-chave anterior.

Com o contêiner mp4, é possível cortar em um quadro não-chave sem recodificar usando uma lista de edição. Em outras palavras, se o quadro-chave mais próximo antes de 3s estiver em 0s, ele copiará o vídeo começando em 0s e usará uma lista de edição para informar ao player para iniciar a reprodução de 3 segundos.

Se você estiver usando o ffmpeg mais recente do git master, ele fará isso usando uma lista de edição quando chamado usando o comando que você forneceu. Se isso não funcionar, provavelmente você está usando uma versão mais antiga do ffmpeg ou o seu player não suporta listas de edição. Alguns players ignoram a lista de edição e sempre reproduzem toda a mídia do arquivo do começo ao fim.

Se você deseja cortar precisamente a partir de um quadro não-chave e deseja que seja reproduzido a partir do ponto desejado em um player que não suporta listas de edição, ou deseja garantir que a parte de corte não esteja realmente no arquivo de saída (por exemplo, se ele contiver informações confidenciais), você poderá fazer isso recodificando para que exista um quadro-chave precisamente no horário de início desejado. Recodificação é o padrão se você não especificar copy. Por exemplo:

ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4

Ao recodificar, você também pode incluir opções adicionais relacionadas à qualidade ou um codificador AAC específico. Para obter detalhes, consulte o Guia de codificação x264 do ffmpeg para vídeo e o Guia de codificação AAC para áudio.

Além disso, a -topção especifica uma duração, não um horário de término. O comando acima codificará 8s de vídeo começando em 3s. Para começar aos 3s e terminar aos 8s, use -t 5. Se você estiver usando uma versão atual do ffmpeg, também poderá substituí -t-lo -tono comando acima para terminar no horário especificado.

mark4o
fonte
4
Existe um atalho para especificar até o final do vídeo?
Jikku Jose
20
@JikkuJose: Omita o -t/ -toe seu argumento para continuar até o fim.
mark4o
41
Nota: é mais rápido fornecer -ssANTES do arquivo de entrada (antes -i), porque dessa forma o ffmpeg irá pular diretamente para o local. No entanto, isso também definirá o horário "zero" para esse local, o que significa que -toapontará para o horário errado. Fonte: trac.ffmpeg.org/wiki/Seeking
Denilson Sá Maia
4
Recebo um problema de sincronização de áudio e vídeo depois de usá-lo ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4, embora o arquivo original não tenha esse problema.
usar o seguinte comando
6
@ user2002522: tente sem o -async 1.
mark4o 28/08/2015
431

Tente usar isso. É a maneira ffmpeg mais rápida e melhor que eu descobri:

 ffmpeg -ss 00:01:00 -i input.mp4 -to 00:02:00 -c copy output.mp4

Este comando corta seu vídeo em segundos!

Eu expliquei isso no meu blog aqui :

-i: especifica o arquivo de entrada. Nesse caso, é (input.mp4).
-ss: Usado com -i, procura no arquivo de entrada (input.mp4) a posição.
00:01:00: Este é o horário em que o vídeo cortado começará.
-to: especifica a duração do início (00:01:40) ao final (00:02:12).
00:02:00: é a hora em que seu vídeo cortado termina.
-c copy: Esta é uma opção para aparar via cópia em fluxo. (Nota: muito rápido)

O formato do tempo é: hh: mm: ss

Observe que a resposta atual altamente votada está desatualizada e a compensação seria extremamente lenta. Para mais informações, consulte este artigo oficial do ffmpeg .

George Chalhoub
fonte
9
isso processou meu arquivo de 45 min 720p em 3s. Essa deve ser a resposta correta.
Dheeraj Bhaskar
7
Você ainda pode sofrer com a falta de quadros-chave com isso. Tomei a sua abordagem para cortar, depois recodifiquei de acordo com a resposta aceita para minimizar o tempo necessário para recodificar.
Pelson
7
Como o @pelson diz, isso cortará os quadros-chave e deixará os primeiros segundos em branco (se o tempo de corte for entre os quadros-chave). Curiosamente, alterando a ordem parâmetro resolve o problema: ffmpeg -ss 00:01:00 -to 00:02:00 -i input.mp4 -ss 00:01:00 -to 00:02:00 -c copy output.mp4. Agora, no entanto, o salto é interrompido e o horário final não está correto (no meu caso).
Raphael
6
Você deve usar esta resposta se não precisar cortar em um milissegundo exato, para que ele selecione o quadro-chave mais próximo disponível. É por isso que é tão rápido que seleciona os quadros-chave mais próximos e retira o snippet sem a necessidade de recodificação. No entanto, se você precisar de um tempo preciso, levar o quadro-chave mais próximo não é suficiente, porque certamente não será exatamente o mesmo. A única solução disponível é recodificar o vídeo, e é por isso que é tão lento. Essa é a única solução, no entanto, se você precisar disso. É por isso que a outra resposta deve ser a aceita, pois esse é o problema da OP.
Yamaneko
4
Não sei por que, mas isso não parece ser mais correto que a resposta aceita, pois isso leva a problemas com quadros-chave ausentes. Para clipes de vídeo curtos, o efeito é inaceitável. A recodificação lenta parece ser a única solução nesses casos.
icarus74
91
ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 -c copy cut.mp4 

Use -c copy para criar instantaneamente. Nesse caso, o ffmpeg não recodificará o vídeo, apenas cortará para o tamanho desejado.

Vlad Hudnitsky
fonte
2
de cópia -c funciona muito bem, mas só se eu remover -async 1
dorien
2
Isso acaba falhando na gravação devido a cabeçalhos inválidos no caso de diferentes contêineres de entrada e saída, por exemplo, entrada .mkv e saída .mp4.
Assil Ksiksi 28/10
1
Certo, para converter .mkv para .mp4 você tem que usar um outro comando: ffmpeg -i movie.mkv -vcodec copy -acodec copy converted_movie.mp4e vice-versa
Vlad Hudnitsky
Quais são as vantagens da recodificação? É de alguma utilidade se queremos apenas vídeos menores no mesmo formato?
Harsha
29
    ffmpeg -i movie.mp4 -vf trim=3:8 cut.mp4

Largue tudo, exceto do segundo 3 para o segundo 8.

JFMD
fonte
4
Eu recebo os primeiros 8 segundos com isso, com os primeiros 3 segundos congelados no primeiro quadro. Corrigido pelo setpts=PTS-STARTPTSfiltro de encadeamento após o filtro de compensação.
jiggunjer
Isso diz "O codificador 'aac' é experimental, mas os codecs experimentais não estão ativados; adicione '-strict -2' se desejar usá-lo." Adicionar -strict -2 não ajuda. O resultado é um arquivo de tamanho zero.
Ivan
4
@ Ivan, você tentou adicionar -strict -2antes cut.mp4(em oposição ao final da linha de comando)?
Jan Gondol
Ei, você pode me dizer se eu só quero vídeo sem 3 a 8 segundos?
Parth Solanki
1
Isso é super lento
Tessaracter 26/11/19
21

Para cortar com base no horário de início e término do vídeo de origem e evitar fazer cálculos, especifique o horário de término como a opção de entrada e o horário de início como a opção de saída.

ffmpeg -t 1:00 -i input.mpg -ss 45 output.mpg

Isso produzirá um corte de 15 segundos das 0:45 às 1:00.

Isso ocorre porque quando -ssé fornecido como uma opção de saída, o tempo descartado ainda é incluído no tempo total lido da entrada, que é -tusado para saber quando parar. Enquanto que se -ssé dado como uma opção de entrada , a hora de início é buscada e não contada , e é daí que a confusão vem.

É mais lento do que procurar, pois o segmento omitido ainda é processado antes de ser descartado, mas esta é a única maneira de fazê-lo, até onde eu sei. Se você estiver recortando do fundo de um arquivo grande, é mais prudente fazer as contas e usá-las -ssna entrada.

RY
fonte
4
lento, mas a única coisa que funcionou para mim (sem perder quadros de outras respostas)
techkuz
8

Aqui está o que eu uso:

ffmpeg -i input.mkv -ss 00:01:00 -to 00:02:00 -c:v copy -c:a copy output.mp4

mp4Arquivos gerados também podem ser usados ​​no iMovie.

Referência: https://www.arj.no/2018/05/18/trimvideo


Se você deseja concatenar várias cenas cortadas, pode usar o seguinte script:

#!/usr/bin/env python3

import subprocess

name = "batman.mp4"

times = []
times.append(["01:06:00", "01:07:00"])
times.append(["01:08:00", "01:09:00"])

open('concatenate.txt', 'w').close()
for idx, time in enumerate(times):
    output_filename = f"output{idx}.mp4"
    cmd = ["ffmpeg", "-i", name, "-ss", time[0], "-to", time[1], "-c:v", "copy", "-c:a", "copy", output_filename]
    subprocess.check_output(cmd)
    with open("concatenate.txt", "a") as myfile:
        myfile.write(f"file {output_filename}\n")

cmd = ["ffmpeg", "-f", "concat", "-i", "concatenate.txt", "-c", "copy", "final.mp4"]
output = subprocess.check_output(cmd).decode("utf-8").strip()
alper
fonte
Isso já foi respondido embora
Tessaracter 26/11/19
1
Minha abordagem é diferente das respostas aceitas. Eu tentei aqueles que tem mais tempo para construir o arquivo mp4. @Tessaracter
alper
1
Esta é a ÚNICA resposta aqui que funcionou para mim ao cortar um pequeno clipe de um vídeo grande. Isso funciona e RÁPIDO !!! Obrigado
lacostenycoder 15/03
1
De nada, fico feliz por poder ajudar. Consegui encontrar essa resposta depois de tentar várias abordagens. A maioria deles era bem lenta. @lacostenycoder
alper 15/03
Isso não poderia simplesmente usar "-c" com "cópia" em vez de dividir -c: ve ec-a: a?
nstenz
-3

Mesmo com 6 anos de atraso, mas acho que todas as respostas acima não abordaram adequadamente a pergunta que @kalai está fazendo. O script bash abaixo processará um arquivo de texto no seguinte formato:

URL | start_time | end_time | filename

por exemplo

https://www.youtube.com/watch?v=iUDURCrvrMI|00:02:02|00:03:41|1

e percorrer o arquivo, o download do arquivo que youtube-dlsuportes, calculando duração entre start_timee end_timee passá-la para ffmpeg, uma vez que -té realmente a duração , não o realend_time

Bata-me se você tiver alguma dúvida.

    for i in $(<video.txt);
    do
        URL=`echo $i | cut -d "|" -f 1`;
        START=`echo $i | cut -d "|" -f 2`;
        END=`echo $i | cut -d "|" -f 3`;
        FILE=`echo $i | cut -d "|" -f 4`;

        SEC1=`echo $START | sed 's/^/((/; s/:/)*60+/g' | bc`
        SEC2=`echo $END | sed 's/^/((/; s/:/)*60+/g' | bc`

        DIFFSEC=`expr ${SEC2} - ${SEC1}`

        ffmpeg $(youtube-dl -g $URL | sed "s/.*/-ss $START -i &/") -t $DIFFSEC -c copy $FILE".mkv";
        ffmpeg -i $FILE".mkv" -f mp3 -ab 192000 -vn $FILE".mp3";
        rm $FILE".mkv";
    done;
rolodex
fonte
Isso gera apenas um arquivo de áudio mp3 e NÃO um vídeo.
lacostenycoder 15/03
Sim ... apenas mude o formato de saída.
rolodex 22/04