Розрізання відеозаписів на основі часу початку та закінчення за допомогою ffmpeg


510

Я спробував вирізати відео, використовуючи час початку та закінчення відео, використовуючи наступну команду

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

За допомогою зазначених вище команд я хочу вирізати відео з 00:00:03в 00:00:08. Але це не обрізання відео між тими часами, а замість того, що воно ріже відео з першими 11 секундами. хтось може допомогти мені, як вирішити це?

Редагувати 1:

Я намагався вирізати, використовуючи наступну команду, яку пропонує mark4o

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

Але була виявлена ​​наступна помилка.

кодер "aac" експериментальний, але експериментальні кодеки не увімкнено

тому я додав -strict -2в команду, тобто,

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

Зараз це працює чудово.


3
Відсутній повний нерозрізаний вихід консолі ffmpeg. Будь ласка, завжди додайте це, коли запитуєте. Дякую.
slhck

3
Звідки ви взяли -стриг 2? Цікаво, як це не в документах: ffmpeg.org/ffmpeg.html
StackOverflowed

Її якість після встановлення ffmpeg. У довідці ffmpeg ви можете знайти цей варіант
Калай


1
Я думаю, що проблема тут була насправді лише в тому, що ви ставите з і до ПЕРЕД -I movie.mp4. Аргументи цього потоку йдуть ПІСЛЯ цього, правда? Тому працював інший шлях. = /
Brent Rittenhouse

Відповіді:


573

У вас, ймовірно, немає ключового кадру на позначці 3 секунди. Оскільки не-ключові кадри кодують відмінності від інших кадрів, їм потрібні всі дані, починаючи з попереднього ключового кадру.

З контейнером mp4 можна вирізати неметалічний кадр без повторного кодування за допомогою списку редагування. Іншими словами, якщо найближчий ключовий кадр до 3s - це 0s, він скопіює відео, починаючи з 0s, і скористається списком редагування, щоб повідомити гравцеві почати відтворення 3 секунди.

Якщо ви використовуєте останню ffmpeg від git master, це зробить це за допомогою списку редагування, коли викликається за допомогою команди, яку ви надали. Якщо це не працює для вас, ви, ймовірно, або використовуєте старішу версію ffmpeg, або ваш плеєр не підтримує редагування списків. Деякі гравці ігнорують список редагування та завжди відтворюватимуть усі медіафайли у файлі від початку до кінця.

Якщо ви хочете точно вирізати, починаючи з не-ключового кадру, і хочете, щоб він відтворювався, починаючи з потрібної точки на програвачі, який не підтримує редагування списків, або ви хочете переконатися, що вирізана частина фактично не знаходиться у вихідному файлі (наприклад, якщо вона містить конфіденційну інформацію), ви можете це зробити, перекодирувавшись так, що в потрібний час початку буде ключовий кадр. Повторне кодування є типовим, якщо ви не вказуєте copy. Наприклад:

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

Під час повторного кодування ви також можете включити додаткові параметри, що стосуються якості, або певний кодер AAC. Докладніше див. Посібник з кодування відео для ffmpeg x264 для відео та посібник з кодування AAC для аудіо.

Також -tопція вказує тривалість, а не час закінчення. Вищевказана команда буде кодувати 8s відео, починаючи з 3s. Для початку в 3 і закінчення в 8 секунд -t 5. Якщо ви використовуєте останню версію FFmpeg можна також замінити -tз -toв вищенаведеної команді до кінця в заданий час.


4
Чи є ярлик, який потрібно вказати до кінця відео?
Jikku Jose

20
@JikkuJose: Пропустіть -t/ -toта його аргумент, щоб продовжувати до кінця.
mark4o

41
Примітка: швидше подавати -ssДО Вхідного файлу (раніше -i), тому що ffmpeg пропустить безпосередньо до місця. Однак це також встановить час "нуль" для цього місця, тобто означає, що -toвкаже неправильний час. Джерело: trac.ffmpeg.org/wiki/Seeking
Denilson Sá Maia

4
У мене ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4виникає проблема синхронізації аудіо та відео після використання цього , хоча в оригінальному файлі такої проблеми немає.
користувач2002522

6
@ user2002522: Спробуйте без цього -async 1.
mark4o

431

Спробуйте скористатися цим. Це я найшвидший і найкращий ffmpeg-спосіб, як це я зрозумів:

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

Ця команда обрізає ваше відео за лічені секунди!

Я пояснив це на своєму блозі тут :

-i: Це визначає вхідний файл. У такому випадку це так (input.mp4).
-ss: використовується з -i, це шукає у вхідному файлі (input.mp4) для позиціонування.
00:01:00: з цього часу розпочнеться ваше оброблене відео
-до: вказується тривалість від початку (00:01:40) до кінця (00:02:12).
00:02:00: на цьому закінчиться ваше оброблене відео
-c копія: це варіант обрізки за допомогою потокової копії. (Примітка: Дуже швидко)

Формат часу: hh: mm: ss

Зауважте, що поточна високообоснована відповідь застаріла, і обробка буде надзвичайно повільною. Для отримання додаткової інформації дивіться цю офіційну статтю ffmpeg .


9
це обробило мій 45 хв 720p файл за 3 секунди. Це має бути правильна відповідь.
Dheeraj Bhaskar

7
Ви все ще можете страждати від нестачі ключових кадрів із цим. Я взяв ваш підхід до вирізання, а потім повторно закодований відповідно до прийнятої відповіді, щоб переконатися, що я мінімізував кількість часу, необхідне для того, щоб витратити на перекодування.
Пельсон

7
Як говорить @pelson, це дозволить відрізати ключові кадри та залишити перші кілька секунд порожніми (якщо час різання між ключовими кадрами). Цікаво, що зміна порядку параметра вирішує проблему: ffmpeg -ss 00:01:00 -to 00:02:00 -i input.mp4 -ss 00:01:00 -to 00:02:00 -c copy output.mp4. Однак зараз пропуск порушений, а час закінчення невірний (у моєму випадку).
Рафаель

6
Ви повинні використовувати цю відповідь, якщо вам не потрібно обрізати з точністю мілісекунди, таким чином, вона вибере найближчий ключовий кадр. Ось чому це так швидко, він вибирає найближчі ключові кадри та виймає фрагмент без необхідності перекодування. Однак якщо вам потрібен точний час, взяти найближчий ключовий кадр недостатньо, тому що він точно не збігатиметься. Єдине доступне рішення - це перекодувати відео, і тому це так повільно. Це єдине рішення, хоча вам це потрібно. Ось чому інша відповідь повинна бути прийнятою, оскільки саме це стосувалося ОП.
Яманеко

4
Не знаю, чому, але це не здається більш правильним, ніж прийнята відповідь, оскільки це призводить до проблем із відсутніми кадрами ключів. Для коротких відеокліпів ефект неприйнятний. Повільне перевведення коду здається єдиним рішенням у таких випадках.
icarus74

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

Використовуйте -c копію для внесення миттєво. У такому випадку ffmpeg не буде перекодувати відео, а просто вирізається відповідно до розміру.


2
копії -c працює чудово, але тільки якщо я видаляю -async 1
дорій

2
Це закінчується тим, що не вдалося записати через недійсні заголовки у випадку різних контейнерів вводу та виводу, наприклад .mkv вхід та вихід .mp4.
Ассіль Ксіксі

1
Добре, щоб перетворити .mkv в .mp4, ви повинні використовувати іншу команду: ffmpeg -i movie.mkv -vcodec copy -acodec copy converted_movie.mp4і навпаки
Влад Гудницький

Які переваги перекодування? Чи корисно це, якщо ми просто хочемо менше відео у тому ж форматі?
Харша

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

Перекиньте все, окрім 3 другого до другого 8.


4
Я отримую перші 8 секунд з цим, причому перші 3 секунди застигають на першому кадрі. Виправлено за допомогою ланцюгового setpts=PTS-STARTPTSфільтра після обрізного фільтра.
jiggunjer

Це говорить "Кодер" aac "експериментальний, але експериментальні кодеки не ввімкнено, додайте" -strict -2 ", якщо ви хочете його використовувати." Додавання -стриг -2 не допомагає. Результат - файл нульової довжини.
Іван

4
@Ivan, ви намагалися додати -strict -2раніше cut.mp4(на відміну від кінця командного рядка)?
Ян Гондол

Гей, Ви можете мені сказати, чи хочу я лише відео без 3 - 8 секунди?
Parth Solanki

1
Це супер повільно
Tessaracter

21

Щоб скоротити на основі часу початку та закінчення вихідного відео та уникнути необхідності робити математику, вкажіть час завершення як варіант введення, а час початку - як вихідний варіант.

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

Це призведе до скорочення на 15 секунд з 0:45 до 1:00.

Це пояснюється тим, що коли -ssзадається як вихідний варіант, відкинутий час все ще включається до загального часу, прочитаного з вводу, який -tвикористовує, щоб знати, коли зупинити. Тоді як якщо -ssвказано як вхідний варіант, час початку запитується і не враховується , звідки і виникає плутанина.

Це повільніше, ніж шукати, оскільки опущений сегмент все ще обробляється перед тим, як його відкинути, але це єдиний спосіб зробити це, наскільки я знаю. Якщо ви відсікаєте зображення з великого файлу, то більш доцільно просто робити математику та використовувати -ssдля введення.


4
повільно, але єдине, що працювало для мене (не втрачаючи кадри від інших відповідей)
techkuz

8

Ось що я використовую:

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

Згенеровані mp4файли також можна використовувати в iMovie.

Довідка: https://www.arj.no/2018/05/18/trimvideo


Якщо ви хочете об'єднати декілька сценок вирізання, ви можете скористатися наступним сценарієм:

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

На це вже відповіли
Tessaracter

1
Мій підхід відрізняється від прийнятих відповідей. Я спробував ті, у яких довший час побудувати файл mp4. @Tessaracter
alper

1
Це ТІЛЬКА відповідь тут, яка працювала для мене, щоб вирізати невеликий кліп із Великого відео. Це працює і ШВИДКО !!! Дякую
lacostenycoder

1
Вас вітає, я радий, що можу допомогти. Мені вдалося знайти цю відповідь, спробувавши багато підходів. Більшість із них були досить повільними. @lacostenycoder
alper

Чи не може це просто використовувати "-c" з "copy", а не розділяти -c: v і -c: a?
nstenz


-3

Хоча я запізнююся на 6 років, але я вважаю, що всі відповіді, наведені вище, не відповіли належним чином на питання, яке задає @kalai . Сценарій bash нижче буде обробляти текстовий файл у такому форматі:

URL | start_time | end_time | filename

наприклад

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

і цикл через файл, завантажує файл , який youtube-dlпідтримує, обчислення тривалості між start_timeі end_timeі передаючи її ffmpeg, так як -tнасправді тривалість , а не справжнійend_time

Підірвіть мене, якщо у вас є питання.

    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;

Це виводить лише аудіофайл mp3, а НЕ відео.
лакостенікодер

Так ... просто змінити вихідний формат.
rolodex
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.