Обрезка видео по времени начала и окончания с помощью ffmpeg

513

Я попытался вырезать видео, используя время начала и окончания видео, используя следующую команду

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
Откуда вы взяли -strict 2? Просто любопытно, поскольку этого нет в документах: ffmpeg.org/ffmpeg.html
StackOverflowed
Его качество после установки ffmpeg. В справке ffmpeg вы можете найти эту опцию
Kalai
1
superuser.com/questions/138331/using-ffmpeg-to-cut-up-video
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
1
Я думаю, что проблема здесь была на самом деле просто в том, что вы добавили от и до -i movie.mp4. Аргументы в пользу этого потока идут ПОСЛЕ этого, верно? Вот почему другой способ работал. = /
Брент Риттенхаус

Ответы:

576

У вас, вероятно, нет ключевого кадра на отметке 3 секунды. Поскольку не ключевые кадры кодируют отличия от других кадров, им требуются все данные, начиная с предыдущего ключевого кадра.

С контейнером mp4 можно вырезать не ключевой кадр без перекодирования с использованием списка редактирования. Другими словами, если ближайший ключевой кадр до 3 с равен 0, то он скопирует видео, начинающееся с 0, и использует список редактирования, чтобы указать игроку начать воспроизведение через 3 секунды.

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

Если вы хотите точно вырезать, начиная с не ключевого кадра, и хотите, чтобы он воспроизводился, начиная с нужной точки на проигрывателе, который не поддерживает списки редактирования, или хотите убедиться, что вырезанная часть фактически не находится в выходном файле (например, если он содержит конфиденциальную информацию), то вы можете сделать это путем перекодирования, чтобы ключевой кадр был точно в желаемое время начала. Перекодировка используется по умолчанию, если вы не укажете copy. Например:

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

При перекодировании вы также можете включить дополнительные параметры, связанные с качеством, или конкретный кодер AAC. Для получения дополнительной информации см. Руководство по кодированию xf64 ffmpeg для видео и Руководство по кодированию AAC для аудио.

Кроме того, -tопция указывает продолжительность, а не время окончания. Приведенная выше команда будет кодировать 8 секунд видео, начиная с 3 секунд. Для начала в 3с и конца в 8с используйте -t 5. Если вы используете последнюю версию FFmpeg можно также заменить -tс -toв вышеприведенной команде до конца в заданное время.

mark4o
источник
4
Есть ли ярлык для указания до конца видео?
Джикку Хосе
20
@JikkuJose: опустить -t/ -toи его аргумент, чтобы продолжить до конца.
mark4o
41
Примечание: быстрее -ssвводить ДО входного файла (до -i), потому что таким образом ffmpeg будет пропускать непосредственно к месту. Тем не менее, это также установит время «ноль» для этого места, а это означает, что -toбудет указывать на неправильное время. Источник: trac.ffmpeg.org/wiki/Seeking
Денилсон Са Майя
4
После этого ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4возникает проблема синхронизации аудио и видео , хотя в оригинальном файле такой проблемы нет.
user2002522
6
@ user2002522: попробуйте без -async 1.
mark4o
433

Попробуйте использовать это. Это самый быстрый и лучший способ 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: это время, когда начинается ваше обрезанное видео.
-to: Указывает продолжительность от начала (00:01:40) до конца (00:02:12).
00:02:00: Это время, когда закончится ваше обрезанное видео.
-c copy: это опция для обрезки через потоковое копирование. (NB: очень быстро)

Формат синхронизации: чч: мм: сс

Обратите внимание, что текущий ответ с высоким рейтингом устарел, и обрезка будет очень медленной. Для получения дополнительной информации посмотрите эту официальную статью ffmpeg .

Джордж Чалхуб
источник
9
это обработало мой 45-минутный файл 720p за 3 с. Это должен быть правильный ответ.
Дхирадж Бхаскар
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 copy для быстрого создания. В этом случае ffmpeg не перекодирует видео, а просто обрезает его в соответствии с размером.

Влад Худницкий
источник
2
-c copy отлично работает, но только если я удалю -async 1
dorien
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.

JFMD
источник
4
Я получаю первые 8 секунд с этим, с первыми 3 секундами, замороженными на первом кадре. Исправлена setpts=PTS-STARTPTSфильтрами цепочки после фильтра обрезки.
Jiggunjer
Это говорит: «Кодировщик« aac »является экспериментальным, но экспериментальные кодеки не включены, добавьте« -strict -2 », если вы хотите его использовать». Добавление -strict -2 не помогает. Результатом является файл нулевой длины.
Иван
4
@ Иван, ты пробовал добавлять -strict -2раньше cut.mp4(в отличие от конца командной строки)?
Ян Гондоль
Эй, вы можете сказать мне, если я хочу только видео без 3 до 8 секунд?
Парф Соланки
1
Это супер медленный
Tessaracter
21

Чтобы вырезать на основе начального и конечного времени исходного видео и избежать необходимости выполнять математические операции, укажите конечное время в качестве параметра ввода и начальное время в качестве параметра вывода.

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

Это произведет 15-секундное сокращение с 0:45 до 1:00.

Это связано с тем, что когда -ssзадан параметр вывода, выброшенное время по-прежнему включается в общее время, считываемое с входа, которое -tиспользуется для определения момента остановки. Принимая во внимание, что если -ssзадано в качестве параметра ввода , время начала ищется, а не подсчитывается , откуда и возникает путаница.

Это медленнее, чем поиск, так как пропущенный сегмент все еще обрабатывается перед тем, как быть сброшенным, но это единственный способ сделать это, насколько я знаю. Если вы вырезаете изнутри большого файла, более разумно просто посчитать и использовать -ssдля ввода.

RY
источник
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()
Alper
источник
Это уже был дан ответ , хотя
Tessaracter
1
Мой подход отличается от принятых ответов. Я пробовал те, которые имеют больше времени для создания файла mp4. @Tessaracter
Alper
1
Это единственный ответ, который помог мне вырезать небольшой клип из Большого видео. Это работает и быстро! Спасибо
lacostenycoder
1
Добро пожаловать, я рад, что могу помочь. Я смог найти этот ответ после попытки многих подходов. Большинство из них были довольно медленными. @lacostenycoder
Alper
Разве это не может просто использовать "-c" с "копией" вместо разделения -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, а НЕ видео.
lacostenycoder
Да ... просто измените формат вывода.
rolodex