Memotong video berdasarkan waktu mulai dan berakhir menggunakan ffmpeg

513

Saya mencoba memotong video menggunakan waktu mulai dan berakhir video dengan menggunakan perintah berikut

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

Dengan menggunakan perintah di atas saya ingin memotong video dari 00:00:03menjadi 00:00:08. Tapi itu tidak memotong video di antara waktu-waktu itu, bukannya memotong video dengan 11 detik pertama. Adakah yang bisa membantu saya menyelesaikan masalah ini?

Edit 1:

Saya telah mencoba memotong dengan menggunakan perintah berikut yang disarankan oleh mark4o

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

Tetapi ditunjukkan kesalahan berikut.

encoder 'aac' adalah eksperimental tetapi codec eksperimental tidak diaktifkan

jadi saya menambahkan -strict -2ke perintah yaitu,

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

Sekarang berfungsi dengan baik.

Kalai
sumber
3
Output konsol ffmpeg Anda yang belum terpotong tidak ada. Harap selalu sertakan ini saat bertanya. Terima kasih.
slhck
3
Di mana Anda mendapatkan -strict 2 dari? Hanya ingin tahu karena tidak ada dalam dokumen: ffmpeg.org/ffmpeg.html
StackOverflowed
Ini untuk kualitas setelah menginstal ffmpeg, Dalam bantuan ffmpeg Anda dapat menemukan opsi ini
Kalai
1
superuser.com/questions/138331/using-ffmpeg-to-cut-up-video
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
Saya pikir masalahnya di sini sebenarnya hanya fakta bahwa Anda memasukkan dari dan ke SEBELUM -i movie.mp4. Argumen untuk aliran itu SETELAH, kan? Itu sebabnya cara lain berhasil. = /
Brent Rittenhouse

Jawaban:

576

Anda mungkin tidak memiliki bingkai kunci pada tanda 3 detik. Karena frame non-key menyandikan perbedaan dari frame lain, mereka memerlukan semua data yang dimulai dengan frame kunci sebelumnya.

Dengan wadah mp4, dimungkinkan untuk memotong pada kerangka non-key tanpa re-encoding menggunakan daftar edit. Dengan kata lain, jika bingkai kunci terdekat sebelum 3s adalah pada 0s maka itu akan menyalin video mulai dari 0s dan menggunakan daftar edit untuk memberitahu pemain untuk mulai bermain 3 detik.

Jika Anda menggunakan ffmpeg terbaru dari git master, ia akan melakukan ini menggunakan daftar edit ketika dipanggil menggunakan perintah yang Anda berikan. Jika ini tidak berhasil untuk Anda, maka Anda mungkin menggunakan versi ffmpeg yang lebih lama, atau pemain Anda tidak mendukung daftar edit. Beberapa pemain akan mengabaikan daftar edit dan selalu memutar semua media dalam file dari awal hingga akhir.

Jika Anda ingin memotong dengan tepat mulai di kerangka non-key dan ingin bermain mulai pada titik yang diinginkan pada pemain yang tidak mendukung daftar edit, atau ingin memastikan bahwa bagian yang dipotong tidak benar-benar dalam file output (misalnya jika berisi informasi rahasia), maka Anda dapat melakukannya dengan menyandikan ulang sehingga akan ada bingkai kunci tepat pada waktu mulai yang diinginkan. Pengodean ulang adalah default jika Anda tidak menentukan copy. Sebagai contoh:

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

Saat menyandikan ulang, Anda mungkin juga ingin menyertakan opsi terkait kualitas tambahan atau penyandi AAC tertentu. Untuk detailnya, lihat Panduan Pengkodean ffmpeg x264 untuk video dan Panduan Pengkodean AAC untuk audio.

Juga, -topsi menentukan durasi, bukan waktu akhir. Perintah di atas akan menyandikan 8s video mulai dari 3s. Untuk memulai pada 3s dan berakhir pada 8s gunakan -t 5. Jika Anda menggunakan versi ffmpeg saat ini, Anda juga dapat menggantinya -tdengan -toperintah di atas untuk mengakhiri pada waktu yang ditentukan.

mark4o
sumber
4
Apakah ada cara pintas untuk menentukan hingga akhir video?
Jikku Jose
20
@JikkuJose: Abaikan -t/ -todan argumennya untuk melanjutkan sampai akhir.
mark4o
41
Catatan: lebih cepat untuk memasok -ssSEBELUM file input (sebelum -i), karena dengan cara itu ffmpeg akan melompat langsung ke lokasi. Namun, itu juga akan mengatur waktu "nol" ke lokasi itu, yang berarti bahwa -toakan menunjuk ke waktu yang salah. Sumber: trac.ffmpeg.org/wiki/Seeking
Denilson Sá Maia
4
Saya mendapatkan masalah sinkronisasi audio dan video setelah menggunakan ini ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4, meskipun file asli tidak memiliki masalah seperti itu.
user2002522
6
@ user2002522: Coba tanpa -async 1.
mark4o
431

Coba gunakan ini. Ini adalah ffmpeg-cara tercepat dan terbaik yang saya temukan:

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

Perintah ini memotong video Anda dalam hitungan detik!

Saya sudah menjelaskannya di blog saya di sini :

-i: Ini menentukan file input. Dalam hal ini, itu adalah (input.mp4).
-ss: Digunakan dengan -i, ini mencari file input (input.mp4) ke posisi.
00:01:00: Ini saatnya video Anda yang sudah dipangkas akan dimulai.
-to: Ini menentukan durasi dari awal (00:01:40) hingga akhir (00:02:12).
00:02:00: Ini saatnya video Anda yang dipangkas berakhir.
-c copy: Ini adalah opsi untuk memotong melalui stream stream. (NB: Sangat cepat)

Format waktu adalah: jj: mm: dd

Harap perhatikan bahwa jawaban saat ini yang sangat ter-update sudah usang dan trim akan sangat lambat. Untuk informasi lebih lanjut, lihat artikel ffmpeg resmi ini .

George Chalhoub
sumber
9
ini memproses file 45p 720p saya dalam 3s. Ini seharusnya jawaban yang benar.
Dheeraj Bhaskar
7
Anda mungkin masih menderita karena kurangnya keyframe dengan ini. Saya mengambil pendekatan Anda untuk memotong, kemudian mengkodekan ulang sesuai jawaban yang diterima untuk memastikan saya meminimalkan jumlah waktu yang saya butuhkan untuk menghabiskan pengkodean ulang.
pelson
7
Seperti @pelson katakan, ini akan memotong bingkai kunci dan membiarkan beberapa detik pertama kosong (jika waktu pemotongan berada di antara bingkai kunci). Menariknya, mengubah urutan parameter memecahkan masalah: ffmpeg -ss 00:01:00 -to 00:02:00 -i input.mp4 -ss 00:01:00 -to 00:02:00 -c copy output.mp4. Namun, sekarang lompatan rusak dan waktu akhir tidak benar (dalam kasus saya).
Raphael
6
Anda harus menggunakan jawaban ini jika Anda tidak perlu memotong pada milidetik yang tepat, sehingga akan memilih frame kunci terdekat yang tersedia. Itu sebabnya begitu cepat, ia memilih keyframes terdekat dan mengeluarkan snippet tanpa perlu reencoding. Namun, jika Anda memang membutuhkan waktu yang tepat, mengambil kerangka kunci terdekat tidak cukup, karena tentu saja tidak akan sama persis. Satu-satunya solusi yang tersedia adalah me-encode ulang video, dan itulah sebabnya video ini sangat lambat. Namun, itulah satu-satunya solusi jika Anda membutuhkannya. Itu sebabnya jawaban yang lain haruslah jawaban yang diterima, karena itulah yang menjadi masalah OP.
Yamaneko
4
Tidak yakin mengapa tetapi ini tampaknya tidak lebih benar daripada jawaban yang diterima karena ini menyebabkan masalah dengan kerangka kunci yang hilang. Untuk klip video pendek efeknya tidak dapat diterima. Reencode lambat tampaknya menjadi satu-satunya solusi dalam kasus seperti itu.
icarus74
91
ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 -c copy cut.mp4 

Gunakan salinan -c untuk membuat instan. Dalam hal ini ffmpeg tidak akan meng-encode ulang video, hanya akan dipotong sesuai ukuran.

Vlad Hudnitsky
sumber
2
-c copy berfungsi dengan baik, tetapi hanya jika saya menghapus -async 1
dorien
2
Ini akhirnya gagal pada saat penulisan karena tajuk yang tidak valid dalam hal wadah input dan output yang berbeda misalnya input .mkv dan output .mp4.
Assil Ksiksi
1
Baiklah, untuk mengonversi .mkv ke .mp4 Anda harus menggunakan perintah lain: ffmpeg -i movie.mkv -vcodec copy -acodec copy converted_movie.mp4dan sebaliknya
Vlad Hudnitsky
Apa keuntungan dari pengkodean ulang? Apakah ada gunanya jika kita hanya ingin video yang lebih kecil dalam format yang sama?
Harsha
29
    ffmpeg -i movie.mp4 -vf trim=3:8 cut.mp4

Jatuhkan semuanya kecuali dari 3 ke 8 kedua.

JFMD
sumber
4
Saya mendapatkan 8 detik pertama dengan ini, dengan 3 detik pertama dibekukan pada frame pertama. Diperbaiki dengan setpts=PTS-STARTPTSfilter chaining setelah filter trim.
jiggunjer
Ini mengatakan "Encoder 'aac' adalah eksperimental tetapi codec eksperimental tidak diaktifkan, tambahkan '-strict -2' jika Anda ingin menggunakannya." Menambahkan -strict -2 tidak membantu. Hasilnya adalah file dengan panjang nol.
Ivan
4
@Van, apakah Anda mencoba menambahkan -strict -2sebelumnya cut.mp4(sebagai lawan dari akhir baris perintah)?
Jan Gondol
Hei, bisakah Anda memberi tahu saya jika saya hanya ingin video tanpa 3 hingga 8 detik?
Parth Solanki
1
Ini sangat lambat
Tessaracter
21

Untuk memotong berdasarkan waktu mulai dan berakhir dari video sumber dan menghindari keharusan melakukan matematika, tentukan waktu akhir sebagai opsi input dan waktu mulai sebagai opsi output.

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

Ini akan menghasilkan potongan 15 detik dari 0:45 hingga 1:00.

Ini karena ketika -ssdiberikan sebagai opsi output, waktu yang dibuang masih termasuk dalam total waktu yang dibaca dari input, yang -tdigunakan untuk mengetahui kapan harus berhenti. Sedangkan jika -ssdiberikan sebagai opsi input , waktu mulai dicari dan tidak dihitung , dari sanalah kebingungan berasal.

Ini lebih lambat daripada mencari karena segmen yang dihilangkan masih diproses sebelum dibuang, tetapi ini adalah satu-satunya cara untuk melakukannya sejauh yang saya tahu. Jika Anda memotong dari dalam file besar, itu lebih bijaksana untuk hanya melakukan perhitungan dan digunakan -ssuntuk input.

RY
sumber
4
lambat, tetapi satu-satunya hal yang berhasil untuk saya (tanpa kehilangan frame dari jawaban lain)
techkuz
8

Inilah yang saya gunakan:

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

mp4File yang dihasilkan juga dapat digunakan di iMovie.

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


Jika Anda ingin menggabungkan beberapa adegan potongan, Anda dapat menggunakan skrip berikut:

#!/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
sumber
Ini sudah dijawab sekalipun
Tessaracter
1
Pendekatan saya berbeda dari jawaban yang diterima. Saya telah mencoba yang memiliki waktu lebih lama untuk membuat file mp4. @Tessaracter
alper
1
Ini adalah jawaban HANYA di sini yang bekerja untuk saya untuk memotong klip kecil dari video Besar. Ini bekerja dan CEPAT !!! Terima kasih
lacostenycoder
1
Sama-sama, saya senang bisa membantu. Saya dapat menemukan jawaban ini setelah mencoba banyak pendekatan. Kebanyakan dari mereka sangat lambat. @ lacostenycoder
alper
Tidak bisakah ini menggunakan "-c" dengan "copy" alih-alih membagi -c: v dan -c: a?
nstenz
-3

Meskipun saya terlambat 6 tahun, tetapi saya pikir semua jawaban di atas tidak menjawab pertanyaan @kalai dengan benar. Skrip bash di bawah ini akan memproses file teks dalam format berikut:

URL | start_time | end_time | filename

sebagai contoh

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

dan loop melalui file, unduh file yang youtube-dlmendukung, menghitung durasi antara start_timedan end_timedan meneruskannya ffmpeg, karena -tsebenarnya durasi , bukan yang asliend_time

Pukul aku kalau ada pertanyaan.

    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
sumber
Ini hanya menghasilkan file audio mp3 dan BUKAN video.
lacostenycoder
Ya ... ubah saja format output.
rolodex