Tagliare i video in base all'ora di inizio e fine usando ffmpeg


513

Ho provato a tagliare il video usando l'ora di inizio e di fine del video usando il seguente comando

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

Usando il comando sopra voglio tagliare il video da 00:00:03a 00:00:08. Ma non sta tagliando il video tra quei tempi invece di tagliare il video con i primi 11 secondi. qualcuno può aiutarmi come risolvere questo?

Modifica 1:

Ho provato a tagliare usando il seguente comando che è suggerito da mark4o

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

Ma è stato mostrato il seguente errore.

l'encoder 'aac' è sperimentale ma i codec sperimentali non sono abilitati

così ho aggiunto il -strict -2al comando cioè,

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

Ora funziona benissimo.


3
Manca l'output della console ffmpeg completo e non tagliato. Si prega di includere sempre questo quando si chiede. Grazie.
slhck,

3
Da dove hai preso -strict 2? Solo curioso perché non è nei documenti: ffmpeg.org/ffmpeg.html
StackOverflowed

È per qualità dopo aver installato ffmpeg, nell'aiuto di ffmpeg puoi trovare questa opzione
Kalai


1
Penso che il problema qui sia stato proprio il fatto che hai inserito il da e PRIMA del -i movie.mp4. Gli argomenti per quel flusso vanno DOPO, giusto? Ecco perché ha funzionato l'altro modo. = /
Brent Rittenhouse

Risposte:


576

Probabilmente non hai un fotogramma chiave al segno di 3 secondi. Poiché i fotogrammi non chiave codificano le differenze rispetto ad altri fotogrammi, richiedono tutti i dati a partire dal fotogramma chiave precedente.

Con il contenitore mp4 è possibile tagliare in un fotogramma non chiave senza ricodificare utilizzando un elenco di modifica. In altre parole, se il fotogramma chiave più vicino prima di 3 secondi è a 0 secondi, il video verrà copiato a partire da 0 secondi e verrà utilizzato un elenco di modifica per indicare al giocatore di iniziare la riproduzione entro 3 secondi.

Se stai usando l' ultimo ffmpeg dal master git, lo farà usando un elenco di modifica quando invocato usando il comando che hai fornito. Se questo non funziona per te, probabilmente stai utilizzando una versione precedente di ffmpeg o il tuo lettore non supporta gli elenchi di modifica. Alcuni lettori ignoreranno l'elenco di modifica e riprodurranno sempre tutti i file multimediali nel file dall'inizio alla fine.

Se si desidera tagliare con precisione partendo da un fotogramma non chiave e si desidera che inizi a partire dal punto desiderato su un lettore che non supporta gli elenchi di modifica o si desidera garantire che la parte tagliata non si trovi effettivamente nel file di output (ad esempio se contiene informazioni riservate), è possibile farlo ricodificando in modo che ci sia un fotogramma chiave esattamente all'ora di inizio desiderata. La ricodifica è l'impostazione predefinita se non si specifica copy. Per esempio:

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

Quando si ricodifica, è possibile che si desideri includere ulteriori opzioni relative alla qualità o un particolare codificatore AAC. Per i dettagli, consultare la Guida alla codifica x264 di ffmpeg per video e la Guida alla codifica AAC per l'audio.

Inoltre, l' -topzione specifica una durata, non un'ora di fine. Il comando sopra codificherà 8 secondi di video a partire da 3 secondi. Per iniziare a 3 secondi e terminare a 8 secondi usare -t 5. Se stai usando una versione corrente di ffmpeg puoi anche sostituirla -tcon -toil comando sopra per terminare all'ora specificata.


4
Esiste un collegamento da specificare fino alla fine del video?
Jikku Jose,

20
@JikkuJose: ometti il -t/ -toe il suo argomento per continuare fino alla fine.
mark4o

41
Nota: è più veloce fornire -ssPRIMA del file di input (prima -i), perché in questo modo ffmpeg salterà direttamente alla posizione. Tuttavia, ciò imposterà anche il tempo "zero" in quella posizione, il che significa che -toindicherà l'ora sbagliata. Fonte: trac.ffmpeg.org/wiki/Seeking
Denilson Sá Maia,

4
Ottengo un problema di sincronizzazione audio e video dopo averlo usato ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4, anche se il file originale non ha questo problema.
user2002522,

6
@ user2002522: provare senza -async 1.
mark4o,

433

Prova ad usare questo. È il modo ffmpeg più veloce e migliore che io abbia capito:

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

Questo comando ritaglia il tuo video in pochi secondi!

L'ho spiegato sul mio blog qui :

-i: specifica il file di input. In tal caso, lo è (input.mp4).
-ss: usato con -i, cerca nel file di input (input.mp4) da posizionare.
00:01:00: è l'ora in cui inizierà il video ritagliato.
-to: specifica la durata dall'inizio (00:01:40) alla fine (00:02:12).
00:02:00: Questo è il momento in cui termina il video ritagliato.
-c copia: questa è un'opzione per tagliare tramite copia stream. (NB: molto veloce)

Il formato di temporizzazione è: hh: mm: ss

Si noti che l'attuale risposta altamente votata non è aggiornata e che l'assetto sarebbe estremamente lento. Per ulteriori informazioni, guarda questo articolo ufficiale di ffmpeg .


9
questo ha elaborato il mio file 45 min 720p in 3 secondi. Questa dovrebbe essere la risposta corretta.
Dheeraj Bhaskar,

7
Tuttavia, potresti comunque soffrire di una mancanza di fotogrammi chiave. Ho adottato il tuo approccio al taglio, quindi ricodificato secondo la risposta accettata per assicurarmi di ridurre al minimo il tempo necessario per ricodificare.
pelson,

7
Come dice @pelson, questo interromperà i fotogrammi chiave e lascerà vuoti i primi pochi secondi (se il tempo di taglio è tra i fotogrammi chiave). È interessante notare, cambiando l'ordine parametro risolve il 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. Ora, tuttavia, il salto è interrotto e l'ora di fine non è corretta (nel mio caso).
Raffaello,

6
Dovresti usare questa risposta se non hai bisogno di tagliare un millesimo di secondo esatto, quindi selezionerà il fotogramma chiave più vicino disponibile. Ecco perché è così veloce, seleziona i fotogrammi chiave più vicini ed elimina lo snippet senza la necessità di ricodificare. Tuttavia, se hai bisogno di un tempo preciso, prendere il fotogramma chiave più vicino non è sufficiente, perché sicuramente non corrisponderà esattamente. L'unica soluzione disponibile è ricodificare il video ed è per questo che è così lento. Questa è l'unica soluzione, tuttavia, se ne hai bisogno. Ecco perché l'altra risposta dovrebbe essere quella accettata, poiché è questo il problema di OP.
Yamaneko,

4
Non so perché, ma questo non sembra essere più corretto della risposta accettata perché questo porta a problemi con i key frame mancanti. Per brevi video clip l'effetto è inaccettabile. La ricodifica lenta sembra essere l'unica soluzione in questi casi.
icarus74

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

Usa -c copy per make in all'istante. In tal caso, ffmpeg non ricodificherà il video, ma ridurrà le dimensioni corrispondenti.


2
di -c copy funziona alla grande, ma solo se rimuovo -async 1
dorien

2
Ciò finisce per non riuscire a scrivere a causa di intestazioni non valide nel caso di contenitori di input e output diversi, ad esempio input .mkv e .mp4.
Assil Ksiksi,

1
Bene, per convertire .mkv in .mp4 devi usare un altro comando: ffmpeg -i movie.mkv -vcodec copy -acodec copy converted_movie.mp4e viceversa
Vlad Hudnitsky,

Quali sono i vantaggi della ricodifica? È utile se vogliamo solo video più piccoli nello stesso formato?
Harsha,

29
    ffmpeg -i movie.mp4 -vf trim=3:8 cut.mp4

Rilascia tutto tranne dal secondo 3 al secondo 8.


4
Ottengo i primi 8 secondi con questo, con i primi 3 secondi congelati sul primo fotogramma. Risolto mediante il concatenamento del setpts=PTS-STARTPTSfiltro dopo il filtro dell'assetto.
jiggunjer,

Questo dice "L'encoder 'aac' è sperimentale ma i codec sperimentali non sono abilitati, aggiungi '-strict -2' se vuoi usarlo." L'aggiunta di -strict -2 non aiuta. Il risultato è un file di lunghezza zero.
Ivan, il

4
@Ivan, hai provato ad aggiungere -strict -2prima cut.mp4(al contrario della fine della riga di comando)?
Jan Gondol,

Ehi, puoi dirmi se voglio solo video senza 3-8 secondi?
Parth Solanki,

1
Questo è super lento
Tessaracter,

21

Per tagliare in base all'ora di inizio e di fine dal video di origine ed evitare di dover eseguire calcoli matematici, specificare l'ora di fine come opzione di input e l'ora di inizio come opzione di output.

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

Ciò produrrà un taglio di 15 secondi dalle 0:45 all'01: 00.

Questo perché quando -ssviene fornito come opzione di output, il tempo scartato viene comunque incluso nel tempo totale letto dall'input, che -tutilizza per sapere quando fermarsi. Considerando che se -ssviene data come opzione di input , l'ora di inizio viene cercata e non conteggiata , da dove proviene la confusione.

È più lento della ricerca poiché il segmento omesso viene ancora elaborato prima di essere scartato, ma questo è l'unico modo per farlo per quanto ne so. Se stai eseguendo il ritaglio in profondità all'interno di un file di grandi dimensioni, è più prudente fare solo i calcoli e utilizzarlo -ssper l'input.


4
lento, ma l'unica cosa ha funzionato per me (senza perdere i frame dalle altre risposte)
techkuz

8

Ecco cosa uso:

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

I mp4file generati possono anche essere utilizzati in iMovie.

Riferimento: https://www.arj.no/2018/05/18/trimvideo


Se si desidera concatenare più scene di taglio, è possibile utilizzare il seguente 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()

Ciò ha già avuto risposta
Tessaracter il

1
Il mio approccio è diverso dalle risposte accettate. Ho provato quelli che hanno più tempo per costruire il file mp4. @Tessaracter
Alper

1
Questa è l'UNICA risposta che ha funzionato per me nel tagliare una piccola clip da un video di grandi dimensioni. Questo funziona e VELOCE !!! Grazie
lacostenycoder il

1
Prego, sono felice di poterti aiutare. Sono stato in grado di trovare questa risposta dopo aver provato molti approcci. Molti di loro erano piuttosto lenti. @lacostenycoder
Alper

Non potrebbe semplicemente usare "-c" con "copia" invece di dividere -c: v e -c: a?
nstenz,


-3

Anche se sono in ritardo di 6 anni, ma penso che tutte le risposte sopra non rispondano correttamente alla domanda che @kalai sta ponendo. Lo script bash di seguito elaborerà un file di testo nel seguente formato:

URL | start_time | end_time | filename

per esempio

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

e scorrere il file, scaricare il file che youtube-dlsupporta, calcolare la durata tra start_timee end_timee passarlo a ffmpeg, poiché in -trealtà è la durata , non il realeend_time

Colpiscimi se hai qualche domanda.

    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;

Questo produce solo un file audio mp3 e NON un video.
lacostenycoder

Sì ... basta cambiare il formato di output.
rolodex,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.