Cắt video dựa trên thời gian bắt đầu và kết thúc bằng ffmpeg


510

Tôi đã cố gắng cắt video bằng cách sử dụng thời gian bắt đầu và kết thúc của video bằng cách sử dụng lệnh sau

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

Bằng cách sử dụng lệnh trên tôi muốn cắt video từ 00:00:03sang 00:00:08. Nhưng nó không cắt video giữa những lần đó thay vào đó là cắt video với 11 giây đầu tiên. bất cứ ai có thể giúp tôi làm thế nào giải quyết điều này?

Chỉnh sửa 1:

Tôi đã cố gắng cắt bằng cách sử dụng lệnh sau đây được đề xuất bởi mark4o

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

Nhưng nó đã được hiển thị các lỗi sau.

bộ mã hóa 'aac' là thử nghiệm nhưng codec thử nghiệm không được bật

vì vậy tôi đã thêm -strict -2vào lệnh tức là

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

Bây giờ nó đang làm việc tốt.


3
Đầu ra giao diện điều khiển ffmpeg đầy đủ, không bị cắt của bạn bị thiếu. Hãy luôn luôn bao gồm điều này khi yêu cầu. Cảm ơn.
slhck

3
Bạn đã nhận được -strict 2 từ đâu? Chỉ tò mò vì nó không có trong các tài liệu: ffmpeg.org/ffmpeg.html
StackOverflowed

Chất lượng của nó sau khi cài đặt ffmpeg, Trong ffmpeg giúp bạn có thể tìm thấy tùy chọn này
Kalai


1
Tôi nghĩ vấn đề ở đây thực ra chỉ là việc bạn đặt từ và đến TRƯỚC phim -i.mp4. Đối số cho luồng đó đi SAU, phải không? Đó là lý do tại sao cách khác làm việc. = /
Brent Rittenhouse

Câu trả lời:


573

Bạn có thể không có khung hình chính ở mốc 3 giây. Vì các khung hình không mã hóa khác biệt từ các khung khác, nên chúng yêu cầu tất cả dữ liệu bắt đầu với khung hình chính trước đó.

Với bộ chứa mp4, có thể cắt ở một khung không phải là keyframe mà không cần mã hóa lại bằng danh sách chỉnh sửa. Nói cách khác, nếu khung hình chính gần nhất trước 3 giây ở mức 0 thì nó sẽ sao chép video bắt đầu từ 0 giây và sử dụng danh sách chỉnh sửa để báo cho người chơi bắt đầu phát 3 giây.

Nếu bạn đang sử dụng ffmpeg mới nhất từ git master, nó sẽ thực hiện việc này bằng cách sử dụng danh sách chỉnh sửa khi được gọi bằng lệnh mà bạn cung cấp. Nếu điều này không hiệu quả với bạn thì có lẽ bạn đang sử dụng phiên bản cũ hơn của ffmpeg hoặc trình phát của bạn không hỗ trợ danh sách chỉnh sửa. Một số người chơi sẽ bỏ qua danh sách chỉnh sửa và luôn phát tất cả các phương tiện trong tệp từ đầu đến cuối.

Nếu bạn muốn cắt chính xác bắt đầu từ một khung hình không chính và muốn nó phát bắt đầu từ điểm mong muốn trên một trình phát không hỗ trợ danh sách chỉnh sửa hoặc muốn đảm bảo rằng phần bị cắt không thực sự nằm trong tệp đầu ra (ví dụ: nếu nó chứa thông tin bí mật), thì bạn có thể làm điều đó bằng cách mã hóa lại để có một khung hình chính xác tại thời điểm bắt đầu mong muốn. Mã hóa lại là mặc định nếu bạn không chỉ định copy. Ví dụ:

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

Khi mã hóa lại, bạn cũng có thể bao gồm các tùy chọn liên quan đến chất lượng bổ sung hoặc bộ mã hóa AAC cụ thể. Để biết chi tiết, xem Hướng dẫn mã hóa x264 của ffmpeg cho video và Hướng dẫn mã hóa AAC cho âm thanh.

Ngoài ra, -ttùy chọn chỉ định thời lượng, không phải thời gian kết thúc. Lệnh trên sẽ mã hóa 8 giây video bắt đầu từ 3 giây. Để bắt đầu lúc 3 giây và kết thúc lúc 8 giây sử dụng -t 5. Nếu bạn đang sử dụng phiên bản hiện tại của ffmpeg, bạn cũng có thể thay thế -tbằng -tolệnh trên để kết thúc tại thời điểm được chỉ định.


4
Có một phím tắt để chỉ định cho đến cuối video không?
Jikku Jose

20
@JikkuJose: Bỏ qua -t/ -tovà đối số của nó để tiếp tục đến cùng.
mark4o

41
Lưu ý: việc cung cấp -ssTRƯỚC tệp đầu vào (trước -i) nhanh hơn , vì cách đó ffmpeg sẽ bỏ qua trực tiếp đến vị trí. Tuy nhiên, điều đó cũng sẽ đặt thời gian "không" cho vị trí đó, có nghĩa là -tosẽ chỉ đến thời gian sai. Nguồn: trac.ffmpeg.org/wiki/Seeking
Denilson Sá Maia

4
Tôi gặp sự cố đồng bộ hóa âm thanh và video sau khi sử dụng ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4, mặc dù tệp gốc không có vấn đề như vậy.
dùng2002522

6
@ user2002522: Hãy thử mà không có -async 1.
mark4o

431

Hãy thử sử dụng cái này. Đó là cách ffmpeg nhanh nhất và tốt nhất mà tôi đã tìm ra:

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

Lệnh này cắt video của bạn trong vài giây!

Tôi đã giải thích nó trên blog của tôi ở đây :

-i: Cái này chỉ định tệp đầu vào. Trong trường hợp đó, nó là (input.mp4).
-ss: Được sử dụng với -i, điều này tìm kiếm trong tệp đầu vào (input.mp4) đến vị trí.
00:01:00: Đây là thời gian video cắt xén của bạn sẽ bắt đầu.
-to: Điều này chỉ định thời lượng từ đầu (00:01:40) đến hết (00:02:12).
00:02:00: Đây là thời gian video cắt xén của bạn sẽ kết thúc.
-c copy: Đây là một tùy chọn để cắt qua sao chép luồng. (NB: Rất nhanh)

Định dạng thời gian là: hh: mm: ss

Xin lưu ý rằng câu trả lời được đánh giá cao hiện tại đã lỗi thời và phần cắt sẽ cực kỳ chậm. Để biết thêm thông tin, hãy xem bài viết ffmpeg chính thức này .


9
điều này đã xử lý tệp 45 phút 720p của tôi trong 3 giây. Đây phải là câu trả lời chính xác.
Dheeraj Bhaskar

7
Bạn vẫn có thể bị thiếu các khung hình chính với điều này mặc dù. Tôi đã sử dụng cách tiếp cận của bạn để cắt, sau đó mã hóa lại theo câu trả lời được chấp nhận để đảm bảo tôi giảm thiểu lượng thời gian tôi cần để sử dụng mã hóa lại.
pelson

7
Như @pelson nói, điều này sẽ cắt các khung chính và để trống vài giây đầu tiên (nếu thời gian cắt là giữa các khung chính). Thật thú vị, việc thay đổi thứ tự tham số sẽ giải quyết vấn đề : ffmpeg -ss 00:01:00 -to 00:02:00 -i input.mp4 -ss 00:01:00 -to 00:02:00 -c copy output.mp4. Tuy nhiên, bây giờ, bỏ qua bị hỏng và thời gian kết thúc là không chính xác (trong trường hợp của tôi).
Raphael

6
Bạn nên sử dụng câu trả lời này nếu bạn không cần phải cắt theo một milisecond chính xác, do đó nó sẽ chọn khung hình chính gần nhất có sẵn. Đó là lý do tại sao nó quá nhanh, nó chọn các khung hình chính gần nhất và lấy đoạn mã ra mà không cần phải mã hóa lại. Tuy nhiên, nếu bạn cần một thời gian chính xác, lấy keyframe gần nhất là không đủ, bởi vì nó chắc chắn sẽ không khớp chính xác. Giải pháp duy nhất có sẵn là mã hóa lại video và đó là lý do tại sao nó quá chậm. Tuy nhiên, đó là giải pháp duy nhất nếu bạn cần. Đó là lý do tại sao câu trả lời khác phải là câu trả lời được chấp nhận, vì đó là vấn đề của OP.
Yamaneko

4
Không chắc chắn tại sao nhưng điều này dường như không chính xác hơn câu trả lời được chấp nhận vì điều này dẫn đến các vấn đề với các khung khóa bị thiếu. Đối với các video clip ngắn, hiệu quả là không thể chấp nhận được. Reencode chậm dường như là giải pháp duy nhất trong những trường hợp như vậy.
icarus74

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

Sử dụng bản sao -c để thực hiện ngay lập tức. Trong trường hợp đó, ffmpeg sẽ không mã hóa lại video, chỉ cần cắt theo kích thước.


2
Bản sao của -c hoạt động rất tốt, nhưng chỉ khi tôi xóa -async 1
dorien

2
Điều này kết thúc không thành công khi ghi do các tiêu đề không hợp lệ trong trường hợp các thùng chứa đầu vào và đầu ra khác nhau, ví dụ đầu vào .mkv và đầu ra .mp4.
Assil Ksiksi

1
Được rồi, để chuyển đổi .mkv thành .mp4, bạn phải sử dụng một lệnh khác: ffmpeg -i movie.mkv -vcodec copy -acodec copy converted_movie.mp4và ngược lại
Vlad Hudnitsky

Những lợi thế của mã hóa lại là gì? Có sử dụng được không nếu chúng ta chỉ muốn video nhỏ hơn ở cùng định dạng?
Harsha

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

Bỏ tất cả mọi thứ trừ từ thứ hai 3 đến thứ hai 8.


4
Tôi nhận được 8 giây đầu tiên với điều này, với 3 giây đầu tiên bị đóng băng trên khung đầu tiên. Đã sửa lỗi bằng setpts=PTS-STARTPTSbộ lọc xích sau bộ lọc cắt.
jiggunjer

Điều này cho biết "Bộ mã hóa 'aac' là thử nghiệm nhưng codec thử nghiệm không được bật, hãy thêm '-strict -2' nếu bạn muốn sử dụng nó." Thêm -strict -2 không giúp được gì. Kết quả là một tập tin có độ dài bằng không.
Ivan

4
@Ivan, bạn đã thử thêm -strict -2trước đó cut.mp4(trái ngược với cuối dòng lệnh) chưa?
Jan Gondol

Này, bạn có thể cho tôi biết nếu tôi chỉ muốn video mà không có 3 đến 8 giây không?
Parth Solanki

1
Đây là siêu chậm
Tessaracter

21

Để cắt dựa trên thời gian bắt đầu và kết thúc từ video nguồn và tránh phải làm toán, hãy chỉ định thời gian kết thúc là tùy chọn đầu vào và thời gian bắt đầu làm tùy chọn đầu ra.

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

Điều này sẽ tạo ra một cắt giảm 15 giây từ 0h45 đến 1:00.

Điều này là do khi -ssđược đưa ra dưới dạng tùy chọn đầu ra, thời gian bị loại bỏ vẫn được bao gồm trong tổng thời gian đọc từ đầu vào, -tsử dụng để biết khi nào nên dừng. Trong khi nếu -ssđược đưa ra như một tùy chọn đầu vào , thời gian bắt đầu được tìm kiếm và không được tính , đó là nơi mà sự nhầm lẫn xuất phát.

Nó chậm hơn tìm kiếm vì phân đoạn bị bỏ qua vẫn được xử lý trước khi bị loại bỏ, nhưng đây là cách duy nhất để làm điều đó theo như tôi biết. Nếu bạn cắt từ sâu trong một tệp lớn, sẽ tốt hơn nếu chỉ làm toán và sử dụng -sscho đầu vào.


4
chậm, nhưng điều duy nhất làm việc cho tôi (không mất khung từ các câu trả lời khác)
techkuz

8

Đây là những gì tôi sử dụng:

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

Các mp4tập tin được tạo cũng có thể được sử dụng trong iMovie.

Tham khảo: https://www.arj.no/2018/05/18/trimvideo


Nếu bạn muốn ghép nhiều cảnh cắt, bạn có thể sử dụng đoạn script sau:

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

Điều này đã được trả lời mặc dù
Tessaracter

1
Cách tiếp cận của tôi khác với các câu trả lời được chấp nhận. Tôi đã thử những cái có thời gian dài hơn để tạo tập tin mp4. @Tessaracter
bắt đầu

1
Đây là câu trả lời DUY NHẤT ở đây đã giúp tôi cắt một đoạn clip nhỏ từ một video lớn. Điều này hoạt động và NHANH CHÓNG !!! Cảm ơn bạn
lacostenycoder

1
Bạn được chào đón, tôi rất vui vì tôi có thể giúp đỡ. Tôi đã có thể tìm thấy câu trả lời này sau khi thử nhiều cách tiếp cận. Hầu hết trong số họ là khá chậm. @lacostenycoder
thay

Không thể chỉ sử dụng "-c" với "copy" thay vì tách ra -c: v và -c: a?
nstenz


-3

Mặc dù tôi trễ 6 năm nhưng tôi nghĩ tất cả các câu trả lời ở trên không giải quyết đúng câu hỏi mà @kalai đang hỏi. Tập lệnh bash bên dưới sẽ xử lý tệp văn bản theo định dạng sau:

URL | start_time | end_time | filename

ví dụ

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

và lặp qua các tập tin, tải các tập tin mà youtube-dlhỗ trợ, tính toán thời gian giữa start_timeend_timevà đi qua nó để ffmpeg, vì -tthực sự là khoảng thời gian , không phải là thựcend_time

Đánh tôi lên nếu bạn có bất kỳ câu hỏi.

    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;

Điều này chỉ xuất ra một tệp âm thanh mp3 và KHÔNG phải là video.
lacostenycoder

Vâng ... chỉ cần thay đổi định dạng đầu ra.
rolodex
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.