Potong file video secara akurat dari baris perintah

22

Saya mengalami kesulitan menemukan aplikasi cli yang dapat mengambil file video (avi, mkv, dan mp4 lebih disukai) dan memotong klip yang sangat pendek (2-6 detik) dengan ketepatan waktu yang presisi. Saya sudah mencoba ffmpeg , mencoder , avidemux , dan mp4box tetapi mereka semua memotong keyframe yang membuat klip 6+ detik. Apakah ada alat yang akan menyandikan ulang file input dan memotong waktu yang akurat atau memotong secara tidak akurat, menyandi ulang, dan kemudian memotong secara akurat?

curmil
sumber
Anda mungkin harus memasukkan ulang kode sebelum memotong untuk memperbaikinya. Anda mungkin bisa mempercepat dengan memotong dulu kerangka kunci di sekitarnya dan hanya memasukkan ulang snippet.
Nifle
4
Perintah FFmpeg mana yang sudah Anda coba, tepatnya? Saya percaya jika Anda men-decode video sebelumnya (yaitu menempatkan -ssparameter setelah -i ), itu harus lebih akurat.
slhck
1
Trik FFmpeg berhasil! Saya tidak menyadari bahwa pesanan itu sangat penting. Apakah ini sama dengan alat lainnya?
curmil

Jawaban:

23

Memotong video dengan ffmpeg

Anda dapat memotong video secara akurat dengan FFmpeg. Sejak versi 2.5 sangat mudah. Misalnya akan memotong 10 detik, mulai dari 0 menit, 3 detik dan 123 milidetik.

ffmpeg -ss 00:00:03.123 -i input.mp4 -t 10 -c:v libx264 -c:a copy out.mp4

Posisi dan waktu dapat dalam detik atau dalam hh:mm:ss[.xxx]bentuk.

Perhatikan bahwa dalam contoh ini, video akan disandikan ulang menggunakan enkoder x264 ; audio disalin.

Anda juga bisa menggunakan -toalih-alih -tmenentukan titik akhir alih-alih durasinya. Dalam hal ini, bagaimanapun, -toadalah setara dengan -t, karena dengan meletakkan -ssdi depan -i, ffmpeg pertama-tama akan mencari ke titik itu dan kemudian mulai menghasilkan.

Lihat juga entri Mencari wiki.


Pemotongan yang akurat untuk ffmpegversi yang lebih lama

Jika Anda memiliki versi ffmpeg yang lebih lama, maka untuk pencarian yang akurat, Anda perlu menempatkan -sssetelahnya -i, yang membuat proses pengkodean sedikit lebih lambat, karena seluruh video harus diterjemahkan terlebih dahulu:

ffmpeg -i input.mp4 -ss 00:00:03.123 -t 10 -c:v libx264 -c:a copy out.mp4

Di sini, -todan -tberperilaku berbeda. -t 10akan membuat klip berdurasi sepuluh detik, sedangkan -to 10akan membuat klip yang berdurasi tujuh detik.

slhck
sumber
Alih-alih -c:v libx264 -c:a libfaacsaya pikir kita bisa menggunakan -acodec copy -vcodec copyyang memberitahu ffmpeg hanya untuk mendeteksi dan menggunakan codec yang sama dengan file aslinya. Adakah yang bisa mengkonfirmasi?
Baodad
2
@ Baodad Anda bisa, tetapi ini tidak akan memotong secara akurat . Saat menyalin bitstream video / audio, ffmpeg perlu memulai pada keyframe, yang mungkin ditempatkan setiap detik atau bahkan lebih jauh.
slhck
Bagaimana cara mengatasi kesalahan "libfaac '" pembuat kode tidak dikenal?
Doug
@ Doug Pilih pembuat enkode yang berbeda, misalnya -c:a aac -strict experimental. Itu solusi paling sederhana.
slhck
1

Satu-satunya alat baris perintah Linux yang saya temukan sejauh ini, yang dapat memotong pada frame yang tepat (atau, dengan akurasi frame), adalah melt( sudo apt-get install melt).

Katakanlah Anda memiliki inputvid.mp4- periksa pengaturan penyandiannya dulu dengan mengatakan ffmpeg(di sini, saya hanya mengatakan saya ingin menyandikannya lagi -f mp4, tetapi sebagai file /dev/nullsehingga keluarannya dibuang; saya mengarahkan stderr agar saya dapat menerimanya - catatan di tengah , perintahnya meminta, dan Anda harus menjawab ydengan ENTER, sehingga proses melanjutkan dan membuang info yang berguna; ini dengan ffmpeg 3.3.3 di Ubuntu 14):

ffmpeg -i inputvid.mp4 -f mp4 /dev/null 2>&1 | grep 'Stream\|encoder'
    Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p(tv, bt709), 640x360 [SAR 1:1 DAR 16:9], 389 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 95 kb/s (default)
y
File '/dev/null' already exists. Overwrite ? [y/N] Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
  Stream #0:1 -> #0:1 (aac (native) -> aac (native))
    encoder         : Lavf57.71.100
    Stream #0:0(und): Video: h264 (libx264) ([33][0][0][0] / 0x0021), yuv420p(progressive), 640x360 [SAR 1:1 DAR 16:9], q=-1--1, 23.98 fps, 24k tbn, 23.98 tbc (default)
      encoder         : Lavc57.89.100 libx264
    Stream #0:1(und): Audio: aac (LC) ([64][0][0][0] / 0x0040), 44100 Hz, stereo, fltp, 128 kb/s (default)
      encoder         : Lavc57.89.100 aac

Ok, jadi kita bisa melihat ffmpeglagi memilih libx264dan aacencoders untuk video ini; maka kita dapat memasukkan ini untuk melt:

melt inputvid.mp4 in=7235 out=7349 -consumer avformat:cut.mp4 acodec=aac vcodec=libx264

.... dan meltakan memotong dengan bagian di antara frame 7235 dan 7349 menjadi file baru cut.mp4,. Kemudian untuk memeriksa apakah cut.mp4loop benar, gunakan meltlagi untuk memutarnya dua kali - dan putar ke jendela SDL:

melt cut.mp4 cut.mp4 -consumer sdl

... dan inilah yang ffmpegdilihat untuk file ini:

ffmpeg -i cut.mp4 -f mp4 /dev/null 2>&1 | grep 'Stream\|encoder'    encoder         : Lavf54.20.4
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 640x360 [SAR 1:1 DAR 16:9], 526 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 182 kb/s (default)
y
File '/dev/null' already exists. Overwrite ? [y/N] Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
  Stream #0:1 -> #0:1 (aac (native) -> aac (native))
    encoder         : Lavf57.71.100
    Stream #0:0(und): Video: h264 (libx264) ([33][0][0][0] / 0x0021), yuv420p, 640x360 [SAR 1:1 DAR 16:9], q=-1--1, 23.98 fps, 24k tbn, 23.98 tbc (default)
      encoder         : Lavc57.89.100 libx264
    Stream #0:1(und): Audio: aac (LC) ([64][0][0][0] / 0x0040), 48000 Hz, stereo, fltp, 128 kb/s (default)
      encoder         : Lavc57.89.100 aac

Pengaturan pengkodean video untuk cut.mp4tampaknya identik dengan inputvid.mp4kecuali bitrate video berubah dari 389 kb / s menjadi 526 kb / s, dan juga pengaturan pengodean audio hampir sama, kecuali laju pengambilan sampel berubah dari 44100 ke 48000 Hz; meskipun itu bisa diatur dengan:

melt inputvid.mp4 in=7235 out=7349 -consumer avformat:cut.mp4 acodec=aac ar=44100 ab=95k vcodec=libx264 vb=389k

... Namun, bahkan dengan ini, bitrate video akhir untuk saya berakhir 337 kb / s. Namun, pemotongan lingkaran baik-baik saja (dan itu termasuk audio) ketika diputar dalam satu lingkaran, jadi saya kira ini memang bingkai-akurat ...

sdaau
sumber
1
meltmeng-encode ulang video, dan menggunakan pustaka FFmpeg di bawahnya. Jika Anda mengizinkan pengodean ulang, ffmpeg dapat menghasilkan output yang sama.
Gyan
Terima kasih @yan - tidak menyadarinya (terutama yang meltmenggunakan perpustakaan FFmpeg), senang tahu!
sdaau
Meleleh terlihat lebih mudah digunakan daripada ffmpeg, yang kita butuhkan adalah cara untuk menentukan waktu, terutama kali dalam jam, menit, bentuk detik, atau jam, menit, detik, ms, yang mengubahnya menjadi bingkai yang tepat.
barlop
0

Seperti kata Baodad dalam komentar (saya memposting karena tidak mudah untuk menemukan jika Anda membaca dengan cepat), pendekatan yang lebih baik adalah mendeteksi encoders audio / video secara otomatis oleh ffmpeg, jadi:

ffmpeg -ss 00:05:17.18 -i in.mp4 -t 00:06:29.10 -acodec copy -vcodec copy out.mp4 
  • mulai @ 00: 05: 17.18
  • input = in.mp4
  • stop @ 00: 06: 29.10
  • output = out.mp4
Gilles Quenot
sumber
2
Ini tidak reencode dan tidak memberikan akurasi bingkai.
Andrea Lazzarotto