Videoları ffmpeg kullanarak başlangıç ​​ve bitiş zamanına göre kesme


510

Aşağıdaki komutu kullanarak videoyu başlangıç ​​ve bitiş zamanını kullanarak kesmeye çalıştım

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

Yukarıdaki komutu kullanarak i video kesmek istiyorum 00:00:03için 00:00:08. Ama videoyu o zamanlar arasında kesmiyor, bunun yerine videoyu ilk 11 saniyede kesiyor. Herkes bana bu sorunu nasıl çözebilir?

Düzenleme 1:

Mark4o tarafından önerilen aşağıdaki komutu kullanarak kesmeye çalıştım

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

Ancak aşağıdaki hata gösterildi.

'aac' kodlayıcısı deneyseldir ancak deneysel kodekler etkinleştirilmemiştir

yani -strict -2komuta yani

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

Şimdi iyi çalışıyor.


3
Tam, kesilmemiş ffmpeg konsol çıkışınız eksik. Lütfen sorurken bunu daima ekleyin. Teşekkürler.
slhck

3
Nereden -strict 2 aldın? Belgelerde olmadığı gibi merak ediyorum: ffmpeg.org/ffmpeg.html
StackOverflowed

Onun ffmpeg yükledikten sonra kalite için, ffmpeg size bu seçeneği bulabilirsiniz yardımcı
Kalai


1
Bence buradaki problem aslında -i film.mp4'ten ÖNCE ve ÖNCE koyduğunuz gerçeğiydi. Bu akış için bağımsız değişkenler SONRA gider, değil mi? Bu yüzden tam tersi çalıştı. = /
Brent Rittenhouse

Yanıtlar:


573

Muhtemelen 3 saniye işaretinde bir anahtar kareniz yok. Anahtar kareler dışındaki çerçeveler diğer karelerden farklılıkları kodladığından, önceki anahtar kareden başlayarak tüm verileri gerektirirler.

Mp4 kapsayıcısı ile bir düzenleme listesi kullanarak yeniden kodlama yapmadan anahtar olmayan bir karede kesmek mümkündür. Başka bir deyişle, 3 saniyeden önceki en yakın ana kare 0 saniyeyse, video 0 saniyeden başlayarak kopyalanır ve müzikçalara 3 saniye içinde oynamaya başlamasını bildirmek için bir düzenleme listesi kullanır.

Git master'dan en son ffmpeg kullanıyorsanız, bunu sağladığınız komut kullanılarak çağrıldığında bir düzenleme listesi kullanarak yapar. Bu sizin için çalışmıyorsa, muhtemelen ffmpeg'in eski bir sürümünü kullanıyorsunuz veya oynatıcınız düzenleme listelerini desteklemiyor. Bazı oynatıcılar düzenleme listesini yok sayar ve dosyadaki tüm medyayı baştan sona oynatır.

Anahtar kareden olmayan bir yerden tam olarak kesmek ve düzenleme listelerini desteklemeyen bir oynatıcıda istenen noktada başlamasını istiyorsanız veya kesme bölümünün gerçekten çıktı dosyasında olmadığından emin olmak istiyorsanız (örneğin, gizli bilgiler içeriyorsa), bunu yeniden kodlayarak bunu yapabilirsiniz, böylece bir anahtar kare tam olarak istenen başlangıç ​​zamanında olacaktır. Belirtmezseniz, yeniden kodlama varsayılan değerdir copy. Örneğin:

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

Yeniden kodlama yaparken ayrıca kalite ile ilgili ek seçenekler veya belirli bir AAC kodlayıcı eklemek isteyebilirsiniz. Ayrıntılar için, bkz. Ffmpeg'nin x264 Video için Kodlama Kılavuzu ve ses için AAC Kodlama Kılavuzu .

Ayrıca, -tseçenek bitiş zamanını değil, bir süre belirtir. Yukarıdaki komut 3 saniyeden başlayarak 8 saniyelik video kodlayacaktır. 3s'de başlamak ve 8s'de bitirmek için kullanın -t 5. Eğer siz de yerini alabilir ffmpeg güncel bir sürümünü kullanıyorsanız -tile -tobelirtilen saatte sona yukarıdaki komuta.


4
Videonun sonuna kadar belirtilecek bir kısayol var mı?
Jikku Jose

20
@JikkuJose: Sonuna devam etmek için -t/ -tove argümanını atlayın .
mark4o

41
Not: -ssgiriş dosyasından ÖNCE (daha önce -i) sağlanması daha hızlıdır , çünkü bu şekilde ffmpeg doğrudan konuma atlayacaktır. Ancak, bu aynı zamanda zamanı "sıfır" olarak ayarlar, yani -toyanlış zamanı gösterecektir. Kaynak: trac.ffmpeg.org/wiki/Seeking
Denilson Sá Maia

4
ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4Orijinal dosyada böyle bir sorun olmasa da, kullandıktan sonra ses ve video senkronizasyonu sorunu alıyorum .
user2002522

6
@ user2002522: olmadan deneyin -async 1.
mark4o

431

Bunu kullanmayı deneyin. Bunu anladım en hızlı ve en iyi ffmpeg-yolu:

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

Bu komut videonuzu saniyeler içinde keser!

Burada blogumda açıkladım :

-i: Girdi dosyasını belirtir. Bu durumda (input.mp4) olur.
-ss: -i ile kullanıldığında, bu giriş dosyasında (input.mp4) konumunu arar.
00:01:00: Kesilen videonuzun başlama zamanı.
-to: Bu, başlangıçtan (00:01:40) bitişe (00:02:12) kadar olan süreyi belirtir.
00:02:00: Kesilen videonuzun sona ereceği zamandır.
-c kopya: Bu, akış kopyası yoluyla kırpma seçeneğidir. (Not: Çok hızlı)

Zamanlama biçimi: ss: dd: ss

Mevcut son derece yükseltilmiş cevabın modası geçmiş olduğunu ve süslemenin son derece yavaş olacağını lütfen unutmayın. Daha fazla bilgi için bu resmi ffmpeg makalesine bakın .


9
Bu benim 3s 45 dakika 720p dosya işledi. Bu doğru cevap olmalı.
Dheeraj Bhaskar

7
Yine de bu konuda anahtar kare eksikliğinden muzdarip olabilirsiniz. Kesme yaklaşımınızı aldım, sonra yeniden kodlama için harcadığım süreyi en aza indirdiğimden emin olmak için kabul edilen cevaba göre yeniden kodladım.
pelson

7
@Pelson'un dediği gibi, bu anahtar kareleri kesecek ve ilk birkaç saniyeyi boş bırakacaktır (kesme süresi anahtar kareler arasındaysa). İlginçtir, parametre sırasını değiştirerek sorunu çözer: ffmpeg -ss 00:01:00 -to 00:02:00 -i input.mp4 -ss 00:01:00 -to 00:02:00 -c copy output.mp4. Ancak şimdi, atlama bozuk ve bitiş zamanı doğru değil (benim durumumda).
Raphael

6
Tam bir milisaniyede kırpmanız gerekmiyorsa bu cevabı kullanmalısınız, böylece mevcut en yakın ana kareyi seçecektir. Bu yüzden bu kadar hızlı, en yakın anahtar kareleri seçiyor ve kod parçasını yeniden kodlamaya gerek kalmadan çıkarıyor. Ancak, kesin bir zamana ihtiyacınız varsa, en yakın ana kareyi almak yeterli değildir, çünkü kesinlikle tam olarak eşleşmez. Mevcut tek çözüm videoyu yeniden kodlamaktır ve bu yüzden çok yavaştır. Yine de buna ihtiyacınız varsa tek çözüm budur. Bu yüzden OP'nin sorunu bu yüzden diğer cevap kabul edilmelidir.
Yamaneko

4
Neden olduğundan emin değilim, ancak bu kabul edilen yanıttan daha doğru görünmüyor çünkü bu, eksik anahtar karelerle ilgili sorunlara yol açıyor. Kısa video klipler için efekt kabul edilemez. Bu gibi durumlarda yavaş reencode tek çözüm gibi görünmektedir.
icarus74

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

Anında yapmak için -c kopyasını kullanın . Bu durumda ffmpeg videoyu yeniden kodlamaz, sadece uygun boyuta kesilir.


2
-c kopyası harika çalışıyor, ancak yalnızca -async 1'i kaldırırsam
dorien

2
.Mkv girişi ve .mp4 çıkışı gibi farklı giriş ve çıkış kapları durumunda geçersiz üstbilgiler nedeniyle yazma başarısız olur.
Assil Ksiksi

1
Tamam ffmpeg -i movie.mkv -vcodec copy -acodec copy converted_movie.mp4
.mkv'yi .mp4'e

Yeniden kodlamanın avantajları nelerdir? Aynı formatta daha küçük videolar istersek herhangi bir yarar sağlar mı?
Harsha

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

İkinci 3'ten ikinci 8'e kadar her şeyi bırakın.


4
Bununla ilk 8 saniyeyi alıyorum, ilk 3 saniye ilk karede donmuş. setpts=PTS-STARTPTSTrim filtresinden sonra zincirleme zinciri ile sabitlenir .
jiggunjer

Bu, "aac" kodlayıcısının deneysel olduğunu, ancak deneysel kodeklerin etkinleştirilmediğini, kullanmak istiyorsanız "-strict -2" ifadesini ekleyin. " -Strict -2 eklemek yardımcı olmaz. Sonuç sıfır uzunluklu bir dosyadır.
Ivan

4
@Ivan, daha -strict -2önce eklemeyi denediniz mi cut.mp4(komut satırının sonuna değil)?
Jan Gondol

Hey, sadece 3 ila 8 saniye olmadan video isteyip istemediğimi söyleyebilir misiniz?
Parth Solanki

1
Bu süper yavaş
Tessaracter

21

Kaynak videodan başlangıç ​​ve bitiş zamanına göre kesmek ve matematik yapmak zorunda kalmamak için , bitiş zamanını giriş seçeneği olarak ve başlangıç ​​zamanını çıkış seçeneği olarak belirtin.

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

Bu, 0:45 ila 1:00 arasında 15 saniyelik bir kesim üretecektir.

Bunun nedeni -ss, bir çıktı seçeneği olarak verildiğinde, atılan sürenin yine -tde ne zaman duracağını bilmek için kullanılan girişten okunan toplam süreye dahil edilmesidir. Oysa -ssbir giriş seçeneği olarak verilirse , karışıklığın geldiği başlangıç ​​zamanı aranır ve sayılmaz .

Atlanan segment atılmadan önce hala işlendiğinden, arama yapmaktan daha yavaştır, ancak bunu bildiğim kadarıyla yapmanın tek yolu bu. Büyük bir dosyanın derinliklerinden kırpıyorsanız, sadece matematik yapmak ve -ssgiriş için kullanmak daha ihtiyatlı olur .


4
yavaş, ama benim için işe
yarayan

8

İşte ne kullanıyorum:

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

Oluşturulan mp4dosyalar da kullanılabilir iMovie.

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


Birden çok kesme sahnesini birleştirmek istiyorsanız, aşağıdaki komut dosyasını kullanabilirsiniz:

#!/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()

Bu zaten cevaplandı
Tessaracter

1
Benim yaklaşımım kabul edilen cevaplardan farklı. MP4 dosyasını oluşturmak için daha uzun zaman olanları denedim. @Tessaracter
alper

1
Bu, Büyük bir videodan küçük bir klip kesmek için benim için çalışan SADECE cevap. Bu çalışıyor ve HIZLI !!! Teşekkür ederim
lacostenycoder

1
Rica ederim, yardımcı olabileceğim için mutluyum. Bu yaklaşımı birçok yaklaşımı denedikten sonra bulabildim. Çoğu oldukça yavaştı. @lacostenycoder
alper

Bu, -c: v ve -c: a'yı ayırmak yerine "copy" ile "-c" kullanamaz mı?
nstenz


-3

6 yıl geç kalmama rağmen , yukarıdaki tüm cevapların @kalai'nin sorduğu soruyu doğru bir şekilde ele almadığını düşünüyorum . Aşağıdaki bash betiği bir metin dosyasını aşağıdaki biçimde işleyecektir:

URL | start_time | end_time | filename

Örneğin

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

ve dosyası üzerinden döngü, bu dosyayı indirir youtube-dlarasındaki süreyi hesaplayarak, desteklerin start_timeve end_timeve geçirmeden ffmpegberi, -taslında süresi , gerçek değilend_time

Herhangi bir sorunuz varsa bana vurun.

    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;

Bu, video değil, yalnızca bir mp3 ses dosyası çıkarır.
lacostenycoder

Evet ... sadece çıktı biçimini değiştirin.
rolodex
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.