Продолжение весёлых видеоприключений в мире PowerShell и FFMPEG. Все посты на эту тему можно найти по этому тегу.
Перед нами задача — вырезать фрагмент видеофайла и сохранить его, не растрачивая попусту время на переконвертирование файла. Даже контейнер нужно оставить таким же.
Действуем так: размещаем в папке с целевым видеофайлом утилиту ffmpeg.exe (скачиваем здесь) и PowerShell скрипт следующего содержания:
### Создать папку ###
New-Item -Path cut -ItemType Directory -ErrorAction Ignore | Out-Null
### Убрать пробелы из имени файла ###
dir *.mp4 | ren -NewName { $_.Name -replace ' ','_' }
### Вырезать и сохранить фрагмент из файла MP4 ###
Get-ChildItem -Filter *.mp4 | ForEach-Object {
$timebegin = "00:00:05" # <-- Время начала фрагмента
$timeend = "00:00:10" # <-- Время окончания фрагмента
$cmd = "-i $_ -ss $timebegin -to $timeend -c copy cut\fragment.mp4"
Start-Process -FilePath ffmpeg.exe -ArgumentList $cmd -Wait -NoNewWindow }
В переменной $timebegin задаем время начало фрагмента, который нам нужен, а в $timeend задаем время окончания фрагмента. Важно соблюсти синтаксис оформления переменных: hh:mm:ss.
Чтобы не забивать голову ошибками в имени файла — я добавил функцию замены пробелов на нижнее подчеркивание, а подхват видеофайла заключил в цикл. Соглашусь, что данная мера избыточна для одного файла, но для ряда роликов идентичной продолжительности — вполне оправдана.
Итоговый файл попадёт в папку cut и будет называться fragment.mp4.
Отдельная команда для утилиты ffmpeg выглядит так:
ffmpeg.exe -i video.mp4 -ss 00:00:05 -to 00:00:10 -c copy fragment.mp4
В данной команде параметры -ss и -to как раз и отвечают за фрагментирование видео, а параметр -с copy задаёт прямое копирование потока из исходного файла без конвертации.
Само собой не забываем, что перед выполнением любых PS1 скриптов в системе нужно установить политику выполнения:
Set-ExecutionPolicy Unrestricted -Force.
Теперь попробуем усложнить исходную задачу и представить, что нам нужен перекодированный файл в h264 с сохранением исходного разрешения.
Учитывая, что файл может попасться с весьма экстравагантной конфигурацией кодирования — нужно будет создать временный mts файл.
После пары минут созидания получается вот такой скрипт:
### Создать папку ###
New-Item -Path cut -ItemType Directory -ErrorAction Ignore | Out-Null
### Убрать пробелы из имени файла ###
dir *.mp4 | ren -NewName { $_.Name -replace ' ','_' }
### Создать промежуточный файл ###
Get-ChildItem -Filter *mp4 | ForEach-Object {
$cmd = "-i "+ "$_" + " -c copy " + "$($_.Name).mts"
Start-Process -FilePath ffmpeg.exe -ArgumentList $cmd -Wait -NoNewWindow }
### Вырезать фрагмент из файла MP4 ###
Get-ChildItem -Filter *mts | ForEach-Object {
$timebegin = "00:00:05" # <-- Время начала
$timeend = "00:00:10" # <-- Время окончания
$bitrate = "1500k" # <-- Битрейт видеопотока
$cmd = "-i $_ -ss $timebegin -to $timeend -c:v libx264 -b:v $bitrate -crf 23 -c:a aac -b:a 256k cut\fragment.mp4"
Start-Process -FilePath ffmpeg.exe -ArgumentList $cmd -Wait -NoNewWindow }
### Удалить временный файл ###
Get-ChildItem -Filter *mts | ForEach-Object { Remove-Item -Path $_ }
Обращаю Ваше пристальное внимание, что в код добавилась переменная $bitrate, с помощью которой задаётся скорость потока.