Хотели начать с 38-й секунды, а файл начинается с 35-й? Это классическая история при обрезке FFmpeg. Обычно команда написана верно, но не учтено главное: где стоит -ss и используется ли -c copy. Разбираем оба параметра и границу между «без потери качества» и «точно по кадру».
-ss до или после -i
-ss можно поставить перед входным файлом или перед выходным, поведение будет разным:
Input seek — -ss 00:00:38 -i input.mp4. FFmpeg быстро прыгает к ближайшей ключевой точке, не декодируя весь файл с нуля. Если дальше идёт перекодирование, современный FFmpeg включает accurate seek: лишние кадры после ключевого кадра декодируются и отбрасываются, поэтому точность остаётся покадровой.
Output seek — -i input.mp4 -ss 00:00:38. FFmpeg декодирует видео с самого начала и только потом дойдёт до нужной метки. Точность та же, но большой файл будет резаться заметно медленнее.
| Запись | Скорость | Точность |
|---|---|---|
-ss перед входом + перекодирование | Быстро | По кадру |
-ss после входа | Медленно | По кадру |
-ss перед входом + -c copy | Очень быстро | Только ключевыми кадрами |
Почему -c copy не может быть точным
-c copy не перекодирует файл, а копирует уже закодированные данные. Это быстро и без второй ступени потерь. Но копировать можно только от ключевого кадра.
В длинных GOP, к которым относится H.264, далеко не каждый кадр может стартовать самостоятельно. Пусть вы просите начало в 10,000 с, а ближайший ключевой кадр стоит в 9,600 с. При -c copy FFmpeg возьмёт 9,600 с — начало тихо сдвинется назад. Насколько именно, зависит от интервала между ключевыми кадрами и на глаз не определяется.
Поэтому выбирайте по задаче:
- скорость важнее точности —
-ssперед входом и-c copy; - точность нужна до кадра — перекодируйте.
# Быстро, но начало может сдвинуться к ключевому кадру
ffmpeg -ss 00:00:38 -i input.mp4 -t 00:00:15 -c copy out.mp4
# Медленнее, но точно до кадра
ffmpeg -ss 00:00:38.450 -i input.mp4 -t 00:00:14.500 \
-c:v libx264 -crf 20 -preset medium -c:a aac -b:a 192k out.mp4
Если режем с середины
У нового файла может появиться отрицательная стартовая метка. Некоторые плееры на этом спотыкаются: показывают чёрный экран или не могут прыгнуть к началу. В MP4 обычно помогает выравнивание старта в ноль:
ffmpeg -ss 00:00:38 -i input.mp4 -t 30 -c copy -avoid_negative_ts make_zero out.mp4
-t задаёт длительность, -to — время конца. Используйте один из них, а не оба сразу.
Склейка: мало просто положить файлы в список
Конкатенация без перекодирования — -f concat -c copy — работает быстро и без потерь, но только если все куски совпадают по кодированию: кодек, профиль, разрешение, частота кадров, пиксельный формат, SAR, time base, частота дискретизации и число каналов звука. Любое расхождение оборачивается Non-monotonous DTS, рассинхроном звука или пропавшим звуком во второй половине.
Если куски сняты разными устройствами или выгружены из разных программ, сначала нормализуйте их:
ffmpeg -i a.mp4 -c:v libx264 -r 30 -s 1920x1080 -pix_fmt yuv420p \
-c:a aac -ar 48000 -ac 2 a_std.mp4
ffmpeg -i b.mp4 -c:v libx264 -r 30 -s 1920x1080 -pix_fmt yuv420p \
-c:a aac -ar 48000 -ac 2 b_std.mp4
printf "file 'a_std.mp4'\nfile 'b_std.mp4'\n" > list.txt
ffmpeg -f concat -safe 0 -i list.txt -c copy out.mp4
Если нормализовать нельзя, используйте фильтр concat и примите одно перекодирование.
Попробовать
Обрезка видео позволяет точно выбрать границы, а склейка видео — соединить несколько фрагментов. Оба инструмента работают локально в браузере.
FAQ
В: -c copy — это всегда без потерь?
О: Данные не перекодируются, поэтому новой потери качества от перекодирования нет. Но «без потерь» не значит «точно по кадру»: старт может уйти к ключевому кадру.
В: Почему -ss перед входом всё равно режет неточно?
О: В режиме -c copy он ограничен ключевыми кадрами. Чтобы получить точный старт, нужно перекодировать.
В: Почему после склейки вторая половина без звука? О: Чаще всего у фрагментов разные частота дискретизации или число каналов. Приведите звук к одному формату и склеивайте снова.