====== Скачивание потокового видео ======
===== youtube-dl =====
[[https://github.com/rg3/youtube-dl/releases|Скачать youtube-dl]]\\
[[https://github.com/rg3/youtube-dl/blob/master/README.md|Справка]]
# Обновить youtube-dl
youtube-dl.exe -U
# Скачать ролик в наилучшем возможном качестве
youtube-dl.exe https://www.youtube.com/watch?v=iIbYyHHieUQ
# Вывести все доступные форматы
youtube-dl.exe https://www.youtube.com/watch?v=iIbYyHHieUQ -F
# Скачать аудио и видео отдельно и склеить их
youtube-dl.exe https://www.youtube.com/watch?v=iIbYyHHieUQ -f 137+140
# Скачать аудио самого лучшего качества
youtube-dl.exe https://www.youtube.com/watch?v=iIbYyHHieUQ -f bestaudio
# Вытащить аудио и сконвертировать его в mp3 с качеством 8
# Качество с 0 (лучшее) до 9 (худшее), 8 хорошо для речи
youtube-dl.exe https://www.youtube.com/watch?v=iIbYyHHieUQ `
-x --audio-format mp3 --audio-quality 8
# Скачать самое свежее видео на канале,
# выбрать видео меньше 1000 пкс шириной + отдельно аудиодорожка в m4a,
# положить результат в папку, назвать файл по шаблону,
# убрать несовместимые с ASCII символы.
youtube-dl.exe https://www.youtube.com/channel/UCY649zJeJVhhJa-rvWThZ2g `
--playlist-end 1 -f [width<1000],m4a `
-o "%userprofile%\Downloads\AlexeyUtin-%(upload_date)s-%(title)s-%(id)s.%(ext)s" `
--restrict-filenames
# с индексом, перекодировать в mp3
& youtube-dl.exe -o '%(playlist_title)s/%(playlist_index)s %(title)s.%(ext)s' $url -f bestaudio -x --audio-format mp3 --audio-quality 0
# Скачать плейлист (лучшее аудио), переделать контейнер на opus без перекодировки
yt-dlp -o '%(artist)s - %(playlist_title)s/%(playlist_index)s %(title)s.%(ext)s' https://www.youtube.com/playlist?list=PLrxctldPFxGJACwafqa1juKhit2OUDvnQ -f bestaudio --remux-video opus
# получить имена видео на канале
& youtube-dl.exe https://www.youtube.com/user/user --flat-playlist --get-filename --playlist-end 5
# CSV - номер, имя, ссылка + данные в переменную list
[uri]$url = 'https://www.youtube.com/user/user'
& yt-dlp -i -o '%(playlist_index)s; %(title)s; %(id)s' `
$url.AbsoluteUri --get-filename |
ConvertFrom-Csv -Delimiter ';' -Header num,name,url |
select num,name,@{n="url";e={"https://www.youtube.com/watch?v=" + $_.url}} -OutVariable list |
Export-Csv "D:\temp\$($url.Segments[-1]).csv" -Delimiter ';' -NoTypeInformation -Encoding utf8
# Скачать все аудиофайлы роликов, в названии которых есть Вася Пупкин, после 1 января 2019 г, конвертировать в opus.
& yt-dlp "https://www.youtube.com/c/channel/videos" --match-title "Вася Пупкин" --dateafter 20190101 `
-f worstaudio -o "%(upload_date)s-%(title)s-%(id)s.%(ext)s" -x --audio-format opus
# Работа через прокси
& yt-dlp --proxy "http://user:password@proxy:port" url
# Через Tor Browser
& yt-dlp https://www.dailymotion.com/video/x188ngo --proxy socks5://localhost:9150 -f best
# Видео из Вконтакта
& youtube-dl -u LOGIN -p PASS "$url"
# Скачать видео из плейлиста (если не использовать --no-playlist, то скачается весь список)
& yt-dlp 'https://www.youtube.com/watch?v=iQn7ROnRBkg&list=PLd5tvoxcDFoG3_FdEKIINiio8eyOJh326&index=12' --no-playlist
# Vimeo: если ошибка "Cannot download embed-only video without embedding URL", то надо указать страницу, где это видео встроено:
& yt-dlp https://player.vimeo.com/video/123456789 --referer https://new.site.ru/student/lessons/1234567
# Скачать только субтитры (https://github.com/yt-dlp/yt-dlp#subtitle-options)
& yt-dlp.exe https://www.youtube.com/watch?v=link --skip-download --write-subs --sub-langs ru
# Автосубтитры
& yt-dlp.exe https://www.youtube.com/watch?v=link --skip-download --write-auto-subs --sub-langs ru
# Лучшее качество 720p
& yt-dlp https://www.youtube.com/watch?v=111111111 -f "best[height=720]"
===== Московская филармония =====
([[http://meloman.ru/videos/tchaikovsky-hall/|зал Чайковского]]):
В Firefox нажать F12 для открытия инструментов разработчика, перейти на вкладку "Сеть" (или сразу нажать Ctrl+Shift+E), нажать F5 для перезапуска страницы. Найти в появившемся списке элементов ссылку на плейлист m3u8 или на сам файл mp4 в нужном качестве.
Выполнить в командной строке:
youtube-dl.exe --add-header "referer:http://meloman.facecast.net/v/facecast_player.swf" http://path/index.m3u8
===== invidious =====
Invidious is an alternative front-end to YouTube\\
https://github.com/iv-org/invidious\\
https://invidious.io
# Прямо в папке проекта (подкаталог invidious создастся сам):
git clone https://github.com/iv-org/invidious.git
# Скопировать файлы из подкаталога docker в корень,
# чтобы иметь возможность сборки Dockerfile из стороннего docker-compose
cp invidious/docker/* invidious
# Обновить локальный клон репозитория
cd invidious
git pull origin main
https://docs.invidious.io/Installation.md
===== Видео для тестов =====
Тестовые видеоролики: https://media.xiph.org/video/derf/
Мульфильм [[http://bbb3d.renderfarming.net/download.html|Big Buck Bunny]]
===== NewPipe =====
Для телефонов на Андроиде. https://newpipe.net/\\
Последнее время обновляется редко, и не успевает за изменениями самого Ютуба. Вот свежие беты:\\
https://github.com/TeamNewPipe/NewPipe/pull/9182
====== ffmpeg ======
Документация: http://ffmpeg.org/ffmpeg.html
Wiki: https://trac.ffmpeg.org/wiki/TitleIndex
===== Установка ffmpeg =====
- Download a static build from https://github.com/BtbN/FFmpeg-Builds/releases/tag/latest or https://www.gyan.dev/ffmpeg/builds/.
- Use 7-Zip to unpack it in the folder of your choice.
- Open a command prompt with administrator's rights.\\ **NOTE: Use CMD.exe, do not use Powershell!** The syntax for accessing environment variables is different from the command shown in Step 4 - running it in Powershell will overwrite your System PATH with a bad value.
- Run the command (see note below; in Win7 and Win10, you might want to use the Environmental Variables area of the Windows Control Panel to update PATH):setx /M PATH "path\to\ffmpeg\bin;%PATH%"
**Do not run setx if you have more than 1024 characters in your system PATH variable.** See [[https://superuser.com/questions/387619/overcoming-the-1024-character-limit-with-setx|this post on SuperUser]] that discusses alternatives. Be sure to alter the command so that "path\to" reflects the folder path from your root to "ffmpeg\bin".
# Скачать последний билд в зависимости от разрядности ОС,
# распаковать и положить в $env:SystemDrive\scripts\ffmpeg
$url64 = 'https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-latest-win64-static.zip'
$url32 = 'https://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-latest-win32-static.zip'
$dfold = "$env:SystemDrive\scripts\"
$fffold = "$dfold" + 'ffmpeg'
$dfile = "$fffold" + '.zip'
if ((gcim win32_operatingsystem).OSArchitecture -match 64) {
Write-Host -fore DarkCyan "Качаю 64-битный ffmpeg"; curl $url64 -OutFile $dfile
}
else {
Write-Host -fore DarkCyan "Качаю 32-битный ffmpeg"; curl $url32 -OutFile $dfile
}
Expand-Archive "$dfile" -DestinationPath "$dfold" -Force
$latest = (gci "$dfold" -Directory -Filter ffmpeg-latest-*).FullName
mkdir "$fffold" -ErrorAction SilentlyContinue
Copy-Item "$latest\*" "$fffold" -Recurse -Force
Remove-Item $dfile,$latest -Force -Recurse
# Добавить путь в PATH в Powershell, требуются права админа
#Requires -RunAsAdministrator
$folder = Read-Host "Введите путь для добавления в PATH"
$test = Test-Path -Path "$folder"
if ($test -eq $true) {write-host -fore Yellow "Добавляем $folder, верно?"
$yes = Read-Host "Нажмите цифру 1, чтобы продолжить"
Switch ($yes) {
1 {
$value = $env:path + ';' + "$folder"
Set-ItemProperty -Path 'Registry::HKLM\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value "$value"
if ($? -eq $True) {write-host -fore Green "$folder успешно добавлен в PATH";sleep 2}
else {write-host -fore Red "Операция завершилась с ошибкой";sleep 2}
}
Default {write-host -fore Yellow "Отмена, выход";sleep 2}
}
}
else {Write-Host -fore Red "Путь не существует, выход";sleep 2}
===== Примеры использования =====
# Сделать .mp4 из .ts без перекодировки
ffmpeg -i "C:\temp\input.ts" -c copy output.mp4
# Перекодировать wav в mp3 наилучшего качества
ffmpeg -i input.wav -q:a 0 output.mp3
# Склеить видео и аудио
ffmpeg -i input-video.mov -i input-audio.m4a -c copy output.mov
# Перекодировка DVD ISO в x265
# выбран 1 и 4 поток (видео и звук), начать со второй секунды
# обрезка - размер X:размер Y:отступ X:отступ Y
# отступы отсчитываются от верхнего левого угла кадра
ffmpeg -i '.\Forrest Gump.ISO' -map 0:1 -map 0:4 -c:v libx265 -vf crop=716:356:4:60 -ss 00:00:02 '.\Forrest Gump-cropped.mp4'
# В x265, первые 10 сек, сделать деинтерлейс.
ffmpeg -i '.\video.ts' -c:v libx265 -t 10 -vf yadif '.\video.mov'
# Из DVD в x264, взять только видео и одну звуковую дорожку
# Оставить интерлейс (по умолчанию - top field first, проверять порядок полей перед запуском!)
# звук - в кодек opus (160-192 kbps - Transparent with very low chance of artifacts)
ffmpeg -i "concat:VTS_01_1.VOB|VTS_01_2.VOB|VTS_01_3.VOB|VTS_01_4.VOB" -map 0:1 -map 0:2 -flags +ilme+ildct -c:a libopus -b:a 160k ./dvd.mp4
# Принудительно указать Bottom field first (для x264)
-flags +ilme+ildct -x264opts bff=1
# Принудительно указать Bottom field first (для x265)
-flags +ilme+ildct -x265-params interlace=bff
# --interlace , --no-interlace
# 0. progressive pictures (default)
# 1. top field first
# 2. bottom field first
# Перекодировать в mp3, наихудшее качество, моно, ресэмплинг до 16 kHz (для речи)
# ресэмплинг фактически не оказывает влияния на размер файла, нет особого смысла использовать
& ffmpeg -i '.\input.webm' -ac 1 -ar 16000 -q:a 9 .\output.mp3
# opus для речи
& ffmpeg -i '.\input.webm' -ac 1 -b:a 24k ".\output.opus"
# Пакетная обработка (pwsh 7), https://devblogs.microsoft.com/powershell/powershell-foreach-object-parallel-feature/
#Requires -Version 7.0
$folder = "$env:userprofile\Music\folder"
$files = dir "$folder\*.opus"
cd "$folder"
mkdir .\recoded
$files |ForEach-Object -Parallel {
& ffmpeg -i "$($_.fullname)" -ac 1 -b:a 24k ".\recoded\$($_.name)"
} -ThrottleLimit (gcim win32_processor).ThreadCount
# Склеить несколько файлов без перекодирования (не MPEG-2, для него - concat:VTS_01_1.VOB|VTS_01_2.VOB)
$path = "D:\temp"
(gci "$path\*.mp4").fullname |% {"file '$_'" |Out-File "$path\list.txt" -Append -Encoding default}
mkdir "$path\output"
& ffmpeg -f concat -safe 0 -i "$path\list.txt" -c copy "$path\output\output-$((get-date).tostring("yy-MM-dd-hh-mm-ss")).mp4"
# Статическое изображение + аудио
& ffmpeg -f image2 -loop 1 -framerate 1 -i .\pic.jpg -i .\aud.mp3 -c:a copy -r 1 -shortest .\vid.mp4 -y
# Убрать аудиодорожку
& ffmpeg -i '.\videoAndAudio.mp4' -vcodec copy -an '.\videoOnly.mp4'
# VP9, CRF 40, первые 30 сек, моно
ffmpeg -i 'C:\temp\VID_20230323_210434.mp4' -c:v libvpx-vp9 -vf scale=1280:-1 -crf 40 -b:v 0 -t 30 -ac 1 'C:\temp\VID_20230323_210434.webm' -y
===== Аппаратное ускорение =====
# Поддерживаемые аппаратные методы
ffmpeg -hide_banner -hwaccels
Hardware acceleration methods:
cuda
dxva2
qsv
d3d11va
# Поддерживаемые аппаратные кодеки qsv
ffmpeg -encoders |select-string qsv
ffmpeg -decoders |select-string qsv
# Вывод опций
ffmpeg -h encoder=h264_qsv
ffmpeg -h encoder=hevc_qsv
# Intel Quick Sync (QSV)
# h264_qsv (global_quality (ICQ mode) is similar to crf mode of x264)
& ffmpeg -i .\2020-05-21-all.mov -c:v h264_qsv -profile:v high -global_quality:v 23 -look_ahead 1 -preset slow D:\temp\2020-05-21-all.mp4 -y
# hevc_qsv (main10 profile)
& ffmpeg -i ".\2018-04-25 10-59-32.3gp" -c:v hevc_qsv -profile:v main10 -pix_fmt p010le -global_quality:v 28 -preset slow ".\2018-04-25 10-59-32-hevc-23.mp4" -y
# Пакетная обработка
$folder = "$env:userprofile\Videos\archive"
$files = dir "$folder\*.avi"
cd "$folder"
foreach ($file in $files) {
# Профиль main10
& ffmpeg -i "$($file.fullname)" -c:v hevc_qsv `
-profile:v main10 -pix_fmt p010le -preset slow -global_quality:v 26 `
".\$($file.basename).mp4" -y
}
https://trac.ffmpeg.org/wiki/Hardware/QuickSync
===== Видеофильтры =====
[[https://ffmpeg.org/ffmpeg-filters.html#normalize|normalize]]\\
Normalize RGB video (aka histogram stretching, contrast stretching).
[[https://ffmpeg.org/ffmpeg-filters.html#hqdn3d-1|hqdn3d]] - отличный, быстрый фильтр.\\
This is a high precision/quality 3d denoise filter. It aims to reduce image noise, producing smooth images and making still images really still. **It should enhance compressibility** - это правда.
[[https://ffmpeg.org/ffmpeg-filters.html#bm3d|bm3d]] - неплохо.\\
Denoise frames using Block-Matching 3D algorithm.
atadenoise - очень хорошо.\\
Apply an Adaptive Temporal Averaging Denoiser to the video input.
owdenoise - отлично, медленный.\\
Apply Overcomplete Wavelet denoiser.
removegrain - надо разбираться, сходу не понять.\\
The removegrain filter is a spatial denoiser for progressive video.
smartblur - очень хорошо.\\
Blur the input video without impacting the outlines.
vaguedenoiser - очень хорошо.\\
Apply a wavelet based denoiser.
==== Поворот видео ====
Rotate 90 clockwise:
ffmpeg -i in.mov -vf "transpose=1" out.mov
For the transpose parameter you can pass:
* 0 = 90CounterCLockwise and Vertical Flip (default)
* 1 = 90Clockwise
* 2 = 90CounterClockwise
* 3 = 90Clockwise and Vertical Flip
Use -vf %%"transpose=2,transpose=2"%% for 180 degrees.
==== Изменение размера (resize) ====
# Ширина 1280, высоту рассчитать кратно 1:
ffmpeg -i in.mov -vf scale=1280:-1 out.mov
# Кратно 2:
ffmpeg -i in.mov -vf scale=1280:-2 out.mov
# if you want to stretch the image in such a way to only double the width of the input image,
# you can use something like this (iw = input width, ih = input height):
ffmpeg -i input.jpg -vf scale=iw*2:ih input_double_width.png
# If you want to half the size of the picture, just multiply by .5 or divide by 2:
ffmpeg -i input.jpg -vf "scale=iw*.5:ih*.5" input_half_size.png
ffmpeg -i input.jpg -vf "scale=iw/2:ih/2" input_half_size.png
# Sometimes you want to scale an image, but avoid upscaling it if its dimensions are too low.
# This can be done using min expressions:
ffmpeg -i input.jpg -vf "scale='min(320,iw)':'min(240,ih)'" input_not_upscaled.png
https://trac.ffmpeg.org/wiki/Scaling
==== Стабилизация ====
# в 1 проход - качество не очень
ffmpeg -i '.\shaky video.mp4' -vf deshake '.\stabilized video.mp4'
# 2 прохода - результат гораздо лучше
ffmpeg -i '.\shaky video.mp4' -vf vidstabdetect=stepsize=1:mincontrast=0 -f null -
ffmpeg -i '.\shaky video.mp4' -vf vidstabtransform=input="transforms.trf" '.\stabilized video.mp4'
https://ffmpeg.org/ffmpeg-filters.html#vidstabdetect-1\\
https://ffmpeg.org/ffmpeg-filters.html#vidstabtransform-1
Пакетный режим:
[CmdletBinding()]
param(
[Parameter(Mandatory=$True, HelpMessage="Каталог, где находятся файлы для стабилизации")]
$folder
)
cd "$folder"
$ext = "mp4"
$files = dir "$folder\*.$ext" -File
# vidstabdetect
foreach ($file in $files) {
$fullname = $file.FullName
$trf = $file.Basename + '.trf'
& ffmpeg -i "$fullname" -vf vidstabdetect=result="$trf" -f null -
}
# vidstabtransform + loudnorm
foreach ($file in $files) {
$fullname = $file.FullName
$trf = $file.Basename + '.trf'
$result = $file.Basename + '-stab' + ".$ext"
& ffmpeg -i "$fullname" -vf vidstabtransform=interpol=bicubic:optzoom=2:smoothing=30:input="$trf",normalize=smoothing=60 -af loudnorm=tp=-1.0 -ar 44100 "$folder\$result"
}
# объединить файлы *-stab.$ext
$mark = Get-Date -UFormat "%Y-%m-%d-%H-%M"
dir "$folder\*-stab.$ext" -File |select -expand name |% {echo file` `'$folder`\$_`' |out-file "$folder\$mark.txt" -Append -encoding ASCII}
& ffmpeg -f concat -safe 0 -i "$folder\$mark.txt" -c copy .\vid-combined-$mark.mp4
==== Склеить несколько видео плиткой ====
# вертикально, звук скопировать из второго видео
& ffmpeg -i .\upper.mp4 -i .\lower.mp4 -filter_complex "[0:v][1:v]vstack[v]" -map "[v]" -map 1:1 -c:a copy combined-v.mp4
# чтобы сделать горизонтально - hstack
==== Размыть часть кадра (blur) на определённое время ====
Отрезается кусок кадра и размывается на 34 сек, затем он накладывается на оригинальное видео.
ffmpeg -i .\2020-04-26_17-01-41-desktop.mp4 -filter_complex "[0:v]crop=661:395:52:151,boxblur=10:enable='between(t,0,34)'[fg]; [0:v][fg]overlay=52:151[v]" -map "[v]" -map 0:a -c:a copy .\2020-04-26_17-01-41-desktop-blur.mkv
https://superuser.com/questions/901099/ffmpeg-apply-blur-over-face
==== Распознавание смены сцен ====
Сохраняется первый кадр из каждой новой сцены
ffmpeg -i video.mp4 -filter:v "select=gt(scene\,0.5)" -vsync vfr output/frame%d.jpg
https://superuser.com/questions/1337709/ffmpeg-scene-detection-and-scenecut
==== Деинтерлейс ====
:!: Деинтерлейс лучше вообще не делать, а оставлять чересстрочное видео.\\
Если такой возможности нет, например, в случае с x265, то всегда делать с удвоением кадров (one frame for each field).
bwdif (https://ffmpeg.org/ffmpeg-filters.html#bwdif) - наверное, лучший вариант. Удваивает кол-во кадров в секунду.\\
w3fdif (https://ffmpeg.org/ffmpeg-filters.html#w3fdif) - очень хорошо, настройки по умолчанию\\
yadif (https://ffmpeg.org/ffmpeg-filters.html#yadif-1) - быстрый, но есть огрехи. Использовать ''yadif=1'' для удвоения кадров.\\
kerndeint (https://ffmpeg.org/ffmpeg-filters.html#kerndeint) - неважно\\
mcdeint (https://ffmpeg.org/ffmpeg-filters.html#mcdeint) - медленный, не всё обрабатывает\\
nnedi (https://ffmpeg.org/ffmpeg-filters.html#nnedi) - чересчур навороченный\\
===== Качество кодирования =====
Для [[https://trac.ffmpeg.org/wiki/Encode/H.265|x265]] и [[https://trac.ffmpeg.org/wiki/Encode/H.264|x264]]: регулируется параметром -crf 0-51 (чем меньше - тем лучше качество), по умолчанию он 28 для x265 и 23 для x264, при хорошем качестве исходного материала этого достаточно. Если исходник шумный, с чересстрочной развёрткой и т. д., то неплохой вариант -crf 22 для x265.\\ For x264 a subjectively sane range is 17–28. Consider 17 or 18 to be visually lossless or nearly so; it should look the same or nearly the same as the input but it isn't technically lossless.
[[https://trac.ffmpeg.org/wiki/Encode/VP9|VP9]]: 0–63, меньше - лучше. [[https://developers.google.com/media/vp9/settings/vod/|Справка по параметрам]].
The range is exponential, so increasing the CRF value +6 results in roughly half the bitrate / file size, while -6 leads to roughly twice the bitrate.
[[https://slhck.info/video/2017/02/24/crf-guide.html|CRF Guide (Constant Rate Factor in x264 and x265)]]
Для [[https://trac.ffmpeg.org/wiki/Encode/MPEG-4|MPEG4]]: параметр -q:v 1-31 (меньше - лучше качество), хороший вариант -q:v 3.
[[https://trac.ffmpeg.org/wiki/Encode/MP3|MP3]]: -q:a 0-9 (меньше - лучше качество), отличный вариант -q:a 0, очень хороший -q:a 1-2 (всё ещё обеспечивающий [[https://wiki.hydrogenaud.io/index.php?title=Transparency|прозрачность]]), далее по ситуации.
Opus: указывается целевой битрейт (больше - лучше качество), -b:a 6k-510k. По умолчанию 92k, хватит для фильмов. Если аудиодорожка имеет очень важное значение, то прозрачность OPUS обеспечивает примерно начиная с битрейта 160k.\\
[[https://wiki.hydrogenaud.io/index.php?title=Opus#Music_encoding_quality|OPUS music encoding quality]]
[[https://trac.ffmpeg.org/wiki/TheoraVorbisEncodingGuide|Ogg]]: -q:a 0-10, выше - лучше. [[http://wiki.hydrogenaud.io/index.php?title=Recommended_Ogg_Vorbis#Recommended_Encoder_Settings|Most users agree -q 5 achieves transparency]], if the source is the original or lossless. По умолчанию - 3, для музыкальных видео бескомпромиссный вариант - 6 и выше.
[[https://trac.ffmpeg.org/wiki/audio%20types|WAV]]: "нормальный" формат - PCM signed 16-bit little-endian, т. е., ''-c:a pcm_s16le''.
[[https://trac.ffmpeg.org/wiki/AudioChannelManipulation|Управление аудиоканалами в ffmpeg]]
===== Выбор конкретных VOB-файлов в DVD-Video =====
Если брать ISO, то кодировщик захватывает также и видеоряд меню. Чтобы этого избежать, нужно выбирать только конкретный ряд файлов VOB.
Если пишет //Stream map '0:9' matches no streams. To ignore this, add a trailing '?' to the map.// (в данном случае это субтитры), то нужно добавить знак вопроса к этим потокам, например
cd "C:\path to mounted ISO\VIDEO_TS"
ffmpeg -i "concat:VTS_01_1.VOB|VTS_01_2.VOB|VTS_01_3.VOB|VTS_01_4.VOB|VTS_01_5.VOB|VTS_01_6.VOB|VTS_01_7.VOB" -map 0:1 -map -0:3 -map 0:2 -map 0:9? -map 0:6? -c:v libx265 -c:s copy "%userprofile%\Videos\DVD-Video.mkv"
https://www.tech-g.com/2017/01/15/converting-dvd-to-mp4-h264-on-windows/
===== Слайд-шоу (фото в видео) =====
Даны 16 файлов .jpg, имена с 001 до 016, надо сделать из них видео.
# Входная частота кадров - 4, выходная - 30
& ffmpeg -framerate 4 -i %03d.jpg -c:v libx264 -r 30 out.mp4
# Пропорции сторон фото сохранены, размер кадра 1080p
& ffmpeg -framerate 4 -i %03d.jpg -c:v libx264 -vf scale=-1:1080 -r 30 out.mp4
# Пропорции сторон фото сохранены, дорисованы поля (letterbox) до 1920x1080
& ffmpeg -framerate 4 -i %03d.jpg -c:v libx264 -vf "scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2" -r 30 out.mp4
https://superuser.com/questions/547296/resizing-videos-with-ffmpeg-avconv-to-fit-into-static-sized-player\\
https://trac.ffmpeg.org/wiki/Slideshow
Вне зависимости от выходной частоты кадров, если входная нестандартная, то склеить такое видео c другими без перекодировки не получится.
===== Автоматическая резка большой аудиозаписи на сегменты по зонам тишины =====
# Исходный файл
$file = Get-Item -LiteralPath "D:\Музыка\Yamaha W7 demos.wav"
# Отступ до и после полезного сигнала (чтобы треки не начинались сразу один за другим)
$preSec = 0.25
$postSec = 2
# Формат файлов на выходе
$outputExt = ".wav"
$log = (& ffmpeg -i $file.FullName -af silencedetect=n=-50dB -f null - 2>&1) -match '^\[silencedetect'
function replaceFfmpegStdout ($in) {$in -replace '.*?: (\d+\.\d+).*','$1'}
$starts,$ends = $log.where({$_ -match 'silence_end'}, 'Split')
$starts = replaceFfmpegStdout $starts |select -SkipLast 1
$ends = replaceFfmpegStdout $ends |select -Skip 1
$c = 0
$starts |% {
& ffmpeg -y `
-ss ($starts[$c] - $preSec) `
-t ($ends[$c] - $starts[$c] + $postSec) `
-i $file.FullName `
($file.DirectoryName + "\" + "$($file.BaseName) " + ($c+1).tostring("0000") + $outputExt)
$c++
}
[[https://stackoverflow.com/a/36077309/14399046|How to split video or audio by silent parts]]
===== Метаинформация, главы, заголовки =====
Файл с метаинформацией выглядит так:
;FFMETADATA1
title=Полёт на Луну
artist=Нил Армстронг
[CHAPTER]
TIMEBASE=1/1000
START=0
END=498039
title=Туда
[CHAPTER]
;00:08:18.040
TIMEBASE=1/1000
START=498040
END=681359
title=Обратно
[STREAM]
title=Полёт на Луну
Metadata keys or values containing special characters (‘=’, ‘;’, ‘#’, ‘\’ and a newline) must be escaped with a backslash ‘\’.\\
Справка по синтаксису: https://ffmpeg.org/ffmpeg-formats.html#Metadata-1
Кодировка файла должна быть 65001 UTF-8 without BOM. Вшивать в Powershell 7, который умеет корректно работать с UTF-8.
& ffmpeg -i 'D:\temp\video.mp4' -i 'D:\temp\metadata.txt' -map_metadata 1 -c copy 'D:\temp\video-metadata.mp4'
:!: Если TIMEBASE=1/1, тогда можно указывать в секундах.\\
:!: Перенос строк в title не работает, ни с помощью \, ни с помощью `n.
Пересчёт строки времени в секунды
function ConvertTo-Seconds ($str) {
$i = $str -split ':'
switch ($i.count) {
1 {[int]$i[0]} # сек
2 {[int]$i[0] * 60 + [int]$i[1]} # мин:сек
3 {[int]$i[0] * 3600 + [int]$i[1] * 60 + [int]$i[2]} # часы:мин:сек
4 {[int]$i[0] * 86400 + [int]$i[1] * 3600 + [int]$i[2] * 60 + [int]$i[3]} # дни:часы:мин:сек
default {Write-Error "Time format must be `[days:`]`[hours:`]`[minutes:`]"}
}
}
ConvertTo-Seconds "35:34"
2134
ConvertTo-Seconds "07:54:12"
28452
ConvertTo-Seconds "1:09:44:23"
121463
Из DVD можно вытащить таймкоды глав программой [[https://www.videohelp.com/software/ChapterXtractor|ChapterXtractor]]. Чтобы программа сама составляла нужный файл метаданных для ffmpeg, нужно в ChapterXtractor.ini добавить следующее:
Preset 7=For ffmpeg metadata
Format 7=\n[CHAPTER]\nTIMEBASE=1/1000\nSTART=%ams\nEND=\ntitle=\n
Header 7=;FFMETADATA1\ntitle=\nartist=\n
Footer 7=\n[STREAM]\ntitle=
Затем, открыв в программе нужный файл .IFO, просто выбрать нужный шаблон на вкладке Format.
ℹ️ Время окончания раздела (END=) добавлять необязательно, достаточно начала (START=).
==== Субтитры ====
Добавить субтитры в видеофайл
& ffmpeg -i .\video.mp4 -i .\english.srt -i .\russian.srt `
-map 0 -map 1 -map 2 -c:v copy -c:a copy -c:s mov_text `
-metadata:s:s:0 language=eng `
-metadata:s:s:1 language=rus `
.\output.mp4
==== Скрипт черновой генерации файла с метадатой ====
Генерирует в из столбика с временными метками вида 00:16:26.120, выгруженного программой ChapterGrabber, файл с метадатой, автоматически пересчитывая метки в миллисекунды.
FIXME
$title="Полёт на Луну"
$artist="Нил Армстронг"
$p=$env:userprofile\Videos\ISO
$ts=gc $p\VTS_01_0.txt
$c=1
Start-Transcript -Path $p\metadata.txt
echo ";FFMETADATA1"
echo "title=$title"
echo "artist=$artist"
echo "[CHAPTER]"
echo "TIMEBASE=1/1000"
echo "START=0"
foreach ($t in $ts) {
$tms=[TimeSpan]::Parse("$t").TotalMilliSeconds
$tmsend=$tms-1
echo "END=$tmsend"
echo "title=Chapter $c"
$c++
echo "[CHAPTER]"
echo "TIMEBASE=1/1000"
echo "START=$tms"
}
echo "[STREAM]"
echo "title=$title"
Stop-Transcript
Закодировать DVD c добавлением метаинформации:
ffmpeg -i "concat:VTS_01_1.VOB|VTS_01_2.VOB|VTS_01_3.VOB|VTS_01_4.VOB" -i "%userprofile%\Videos\metadata.txt" -map 0:1 -map 0:2 -map_metadata 1 -c:v libx265 -vf yadif "%userprofile%\Videos\DVD.mkv"
Просто добавить информацию в уже готовый файл:
ffmpeg -i DVD.mkv -i "%userprofile%\Videos\metadata.txt" -map_metadata 1 -c copy "%userprofile%\Videos\DVD2.mkv"
Выгрузить метаданные из файла:
ffmpeg -i DVD.mkv -f ffmetadata meta.txt
Полезная информация:\\
https://multimedia.cx/eggs/supplying-ffmpeg-with-metadata/\\
https://medium.com/@dathanbennett/adding-chapters-to-an-mp4-file-using-ffmpeg-5e43df269687\\
https://newspaint.wordpress.com/2016/07/27/ripping-a-video-from-dvd-using-ffmpeg/\\
https://en.wikibooks.org/wiki/FFMPEG_An_Intermediate_Guide/subtitle_options
==== Конвертер таймкодов на Youtube в ffmpeg metadata ====
Было:
00:00 ул. Сталеваров
...
1:53:04 Саянская ул.
Стало:
;FFMETADATA1
title=2020.07.28 Электрозавод - Яуза - Рязанский проспект
artist=
[CHAPTER]
TIMEBASE=1/1
START=0
END=134
title=ул. Сталеваров
...
[CHAPTER]
TIMEBASE=1/1
START=6784
END=
title=Саянская ул.
[STREAM]
title=2020.07.28 Электрозавод - Яуза - Рязанский проспект
$srcFile = Get-Item "$env:userprofile\Videos\2020.07.28 Электрозавод - Яуза - Рязанский проспект.txt"
$source = (gc "$srcFile") -match "\d:\d"
# seconds and custom object
$timeTable = @()
$source |% {
$str = $_ -split '\s+',2
if ($str[0] -notmatch ":\d+:") {$str[0] = '00:' + $str[0]}
$obj = [PSCustomObject]@{
start = ([datetime]$str[0]).TimeOfDay.TotalSeconds
end = ''
name = $str[1]
}
$timeTable += $obj
}
# + end time
$timeTable |sort start -Descending |% {
if ($startPrev) {$_.end = $startPrev}
$startPrev = $_.start
}
# create ffmpeg metadata
$ffmpegMeta = $timetable |% {"
[CHAPTER]
TIMEBASE=1/1
START=$($_.start)
END=$($_.end)
title=$($_.name)
"
}
$ffmpegMeta = ";FFMETADATA1
title=$($srcFile.basename)
artist=
" + $ffmpegMeta + "
[STREAM]
title=$($srcFile.basename)"
# dump to disk
$ffmpegMeta |Out-File "$($srcFile.DirectoryName + '\' + $srcFile.BaseName + '-ffmpegMetadata' + $srcFile.Extension)" -Encoding default
==== Вытащить описание с Youtube ====
$url = curl 'https://www.youtube.com/watch?v=12345' -UseBasicParsing
($url.Content |select-string '(?<="description":\{"simpleText":").*?(?="\},"lengthSeconds)').Matches.Value -split "\\n"
=====Аудиофильтры =====
==== volume ====
# Определение пиков сигнала (-vn - без видео, это гораздо быстрее)
ffmpeg -i .\file.mkv -vn -af volumedetect -f null -
...
[Parsed_volumedetect_0 @ 000001e2d5e78a00] mean_volume: -27.5 dB
[Parsed_volumedetect_0 @ 000001e2d5e78a00] max_volume: -5.1 dB
...
# Нормализация по max_volume, звук - WAV
ffmpeg -i .\file.mkv -af volume=5.1dB -c:a pcm_s16le -c:v copy .\file-norm.mkv
https://trac.ffmpeg.org/wiki/AudioVolume
==== loudnorm ====
Динамическая нормализация аудио.
Первый проход:
ffmpeg -i in.wav -af loudnorm=I=-20:TP=-1:LRA=20:print_format=json -f null -
Второй проход (ввести в значение measured значения input из результатов первого прохода + offset):
ffmpeg -i in.wav -af loudnorm=I=-20:TP=-1:LRA=20:measured_I=-22.27:measured_TP=0.03:measured_LRA=20.10:measured_thresh=-33.99:offset=0.51:print_format=summary -ar 48k out.wav
Более-менее универсальные настройки:
-af loudnorm=I=-16:TP=-1:LRA=18
Справка: http://ffmpeg.org/ffmpeg-filters.html#loudnorm\\
Статья автора: http://k.ylo.ph/2016/04/04/loudnorm.html\\
Уровень LRA: https://www.audiokinetic.com/en/library/edge/?source=Help&id=monitoring_signal_level#more_on_loudness_range_lra
==== alimiter ====
Лимитер + нормализация. Стандартное значение limit - 1, чем ближе к нулю, тем больше эффект.
ffmpeg -i in.wav -af alimiter=limit=0.1 out.wav
https://ffmpeg.org/ffmpeg-filters.html#alimiter
==== agate ====
Гейт. В примере сочетание с лимитером, начало с 6-й секунды, моно, битрейт 64к.
& ffmpeg -i .\record.wav -af agate=threshold=0.025,alimiter=limit=0.2 -ss 6 -ac 1 -ab 64k .\record.opus
https://ffmpeg.org/ffmpeg-filters.html#agate
==== highpass ====
От бубнежа в записи, отсечка ниже 250 Гц. Этот фильтр с ffplay не работает.
& ffmpeg -i .\record.wav -af agate=threshold=0.025,alimiter=limit=0.2,highpass=f=250 -ac 1 -ab 64k .\record.opus
https://ffmpeg.org/ffmpeg-filters.html#highpass
==== amix - смешивание аудиопотоков ====
# audio.mp3 начинается через 5 сек после начала
& ffmpeg -i "C:\temp\video.mp4" -itsoffset 5s -i "C:\temp\audio.mp3" -map 0 -map 1 -async 1 -filter_complex amix=inputs=2 -c:v copy "C:\temp\output.mp4"
https://ffmpeg.org/ffmpeg-filters.html#amix
==== rubberband - изменение скорости и высоты ====
# 40% от оригинального темпа
& ffplay -i '.\audio.mp3' -af rubberband=tempo=0.4:pitchq=quality
https://ffmpeg.org/ffmpeg-filters.html#rubberband
==== speechnorm - нормализация речи ====
# Weak and slow amplification:
speechnorm=e=3:r=0.00001:l=1
# Moderate and slow amplification:
speechnorm=e=6.25:r=0.00001:l=1
# Strong and fast amplification:
speechnorm=e=12.5:r=0.0001:l=1
# Very strong and fast amplification:
speechnorm=e=25:r=0.0001:l=1
# Extreme and fast amplification:
speechnorm=e=50:r=0.0001:l=1
https://ffmpeg.org/ffmpeg-filters.html#speechnorm
===== Пакетная обработка =====
Всё в x265:
set folder=%userprofile%\Videos
mkdir %folder%\Result
for %%a in ("%folder%\*.*") do ffmpeg -i "%%a" -map 0 -c:v libx265 "%folder%\Result\%%~na.mkv"
# -> MP3 44100 Гц 16 бит:
[CmdletBinding()]
param(
[Parameter(Mandatory=$True, HelpMessage="Каталог, где находятся файлы для перекодирования в mp3")]
$folder = '',
$extin = "flac"
)
$extout = "mp3"
$files = gci -LiteralPath "$folder" -File |? name -match "$extin"
foreach ($file in $files) {
$ifile = $file.FullName
$result = $file.BaseName + '.' + "$extout"
& ffmpeg -i "$ifile" -map 0:0 -q:a 0 -ar 44100 -sample_fmt s16p "$folder\$result"
}
===== Видеозахват =====
Задача: захватывать видео с веб-камеры, звук брать с микрофонного входа.
Вывести список [[http://ffmpeg.org/ffmpeg-devices.html#dshow|устройств DirectShow]]:
ffmpeg -list_devices true -f dshow -i dummy
# Примерный результат:
DirectShow video devices (some may be both video and audio devices)
[dshow @ 0000012cb5b1a140] "B525 HD Webcam"
[dshow @ 0000012cb5b1a140] Alternative name "@device_pnp_\\?\usb#vid_046d&pid_0836&mi_02#7&10304ea4&0&0002#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global"
[dshow @ 0000012cb5b1a140] DirectShow audio devices
[dshow @ 0000012cb5b1a140] "╨Ь╨╕╨║╤А╨╛╤Д╨╛╨╜ (B525 HD Webcam)"
[dshow @ 0000012cb5b1a140] Alternative name "@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{78B33698-9C35-4389-96D6-A4C1FE410B1E}"
[dshow @ 0000012cb5b1a140] "╨б╤В╨╡╤А╨╡╨╛ ╨╝╨╕╨║╤И╨╡╤А (Realtek High Definition Audio)"
[dshow @ 0000012cb5b1a140] Alternative name "@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{3054A90F-0C13-4228-B85A-E8D3A525FAA4}"
[dshow @ 0000012cb5b1a140] "╨Ь╨╕╨║╤А╨╛╤Д╨╛╨╜ (Realtek High Definition Audio)"
[dshow @ 0000012cb5b1a140] Alternative name "@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{F7E26B25-9DE5-4D59-9F8A-2C56A931A566}"
Т. к. названия некоторых устройств идут крякозябрами, нужно использовать альтернативные имена.
# Вывести список свойств устройства:
ffmpeg -f dshow -list_options true -i video="B525 HD Webcam"
# Показать параметры определённого кодировщика или декодера:
ffmpeg -h encoder=mjpeg
ffmpeg -h decoder=flac
Захват:
# Звук с вебкамеры
# $auddev = "@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{E33F0DA4-DD49-40A7-BE50-899260CCB4D5}"
# Звук со стереомикшера
# $auddev = "@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{3054A90F-0C13-4228-B85A-E8D3A525FAA4}"
# Звук с микрофонного входа
$auddev = "@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{F7E26B25-9DE5-4D59-9F8A-2C56A931A566}"
$viddev = "B525 HD Webcam"
$buffer = "150M"
$timestamp = get-date -UFormat "%Y-%m-%d_%H-%M-%S"
# Захват в x264 (-movflags +faststart - вроде для Youtube хорошо)
& ffmpeg -f dshow -rtbufsize $buffer -i video="$viddev":audio="$auddev" -preset ultrafast -tune zerolatency -movflags +faststart $env:USERPROFILE\Videos\$timestamp.mp4
# Захват как есть, что выдаёт камера (выбран входной поток mjpeg, FHD, 30 fps)
& ffmpeg -f dshow -rtbufsize $buffer -video_size 1920x1080 -framerate 30 -vcodec mjpeg -i video="$viddev":audio="$auddev" -c copy $env:USERPROFILE\Videos\out.mkv
# Захват как есть 1280x720
& ffmpeg -f dshow -rtbufsize $buffer -video_size 1280x720 -framerate 30 -vcodec mjpeg -i video="$viddev":audio="$auddev" -c copy $env:USERPROFILE\Videos\$timestamp.mkv
# Вариант с AVI (видео FMP4 почти макс. качества (макс. - 2), аудио MP3 - максимального)
& ffmpeg -f dshow -rtbufsize $buffer -i video="$viddev":audio="$auddev" -q:v 3 -q:a 0 $env:USERPROFILE\Videos\$timestamp.avi
# AVI, ограничить кол-во кадров до 25, разрешение - до 1024×576.
& ffmpeg -f dshow -rtbufsize $buffer -i video="$viddev":audio="$auddev" -r 25 -s 1024x576 -q:v 3 -q:a 0 $env:USERPROFILE\Videos\$timestamp.avi
https://trac.ffmpeg.org/wiki/DirectShow
==== Параметры перекодирования после захвата ====
Исходник шумный, MJPEG 1280x720, WAV 44100.\\
Обработка: звук - простая нормализация до -1 дБ, видео - два фильтра: hqdn3d для уменьшения шума и normalize для нормализации цветности.
# В x265 + OPUS, архив
ffmpeg -i input.mkv -c:v libx265 -crf 24 -preset slow -vf hqdn3d,normalize -c:a libopus -b:a 256k output.mkv
# В x264 + aac, для браузеров
ffmpeg -i input.mkv -crf 20 -preset slow -vf hqdn3d,normalize -b:a 256k output.mp4
# Пример обработки захваченного куска:
cd ~\Videos
$name = '2023-12-12_21-35-35'
# Вырезать нужную часть
ffmpeg -i .\${name}.mkv -ss 5:42 -t 3:12 -c copy .\${name}_edit.mkv
# Измерить пик громкости
Invoke-Expression "
& ffmpeg -i .\${name}_edit.mkv -vn -af volumedetect -f null -
" -ErrorVariable vol
$vol = ($vol -match 'max_volume:') -replace '.*?-?(\S+) dB','$1'
# Кодировать + нормализовать аудио на основе измеренного пика громкости
& ffmpeg.exe -i ".\${name}_edit.mkv" -c:v hevc_qsv `
-profile:v main10 -pix_fmt p010le -preset slower `
-global_quality:v 24 -tag:v hvc1 `
-af volume=${vol}dB -c:a libopus -b:a 256k `
".\${name}_norm2.mp4" -y
===== Захват экрана =====
В Windows 2 способа - gdigrab (встроенный, звук писать не умеет) и DirectShow (необходимо иметь фильтр, типа [[http://www.umediaserver.net/components/index.html|UScreenCapture]]). Можно комбинировать оба способа.
# Посмотреть наличие устройств DirectShow
ffmpeg -list_devices true -f dshow -i dummy
# Захват полного экрана со звуком
ffmpeg -f gdigrab -i desktop -f dshow -i audio="Microphone (High Definition Aud" "c:\temp\$((get-date).tostring("yyyy-MM-dd_HH-mm-ss"))-ScreenCapture.mp4"
# Захват окна, без звука, 6 кадров/с
ffmpeg -f gdigrab -framerate 6 -i title=Calculator out.mpg
# Захват экрана со второго монитора, мышь не показывать, звук моно
& ffmpeg -f gdigrab -rtbufsize 1500M -framerate 30 -offset_x 1920 -offset_y 0 -video_size 1600x1200 -draw_mouse 0 -i desktop `
-f dshow -i audio="Стерео микшер (Realtek High Definition Audio)" `
-c:v h264_qsv -profile:v high -global_quality:v 23 -b:a 64k -ac 1 `
D:\temp\$(get-date -f yyyy-MM-dd-HH-mm-ss).mp4
# Захват экрана со второго монитора, аппаратное ускорение, 15 кадров/с, качество 30
& ffmpeg -f gdigrab -framerate 15 -offset_x 1920 -video_size 1920x1080 -i desktop -c:v h264_qsv -profile:v high -global_quality:v 30 D:\Видео\output.mp4 -y
https://trac.ffmpeg.org/wiki/Capture/Desktop\\
https://ffmpeg.org/ffmpeg-devices.html#gdigrab\\
https://www.trishtech.com/2018/02/record-windows-desktop-screen-with-sound-using-ffmpeg/\\
https://medium.com/@colten_jackson/simple-free-screen-capture-with-ffmpeg-3aeddbeb161b\\
https://antumdeluge.wordpress.com/2014/02/19/recording-screen-windows-desktop-using-ffmpeg/
===== Захват экрана + видео с камеры (картинка в картинке, PIP) =====
Качество надо подбирать по вкусу. Здесь захват в -c:v hevc_qsv -q:v 15, вряд ли это оптимальный вариант.
$t = get-date
$auddev = "Микрофон (B525 HD Webcam)"
$viddev = "B525 HD Webcam"
$screenRes = gwmi Win32_VideoController |select CurrentHorizontalResolution,CurrentVerticalResolution
$camWidth = 320
$camHeight = 240
# Оверлей - вычисляется левый верхний угол. Если написать
# "overlay=main_w-overlay_w-0:main_h-overlay_h-0" - это правый нижний угол.
& ffmpeg `
-f gdigrab -thread_queue_size 1024 -i desktop `
-f dshow -rtbufsize 1500M -video_size "$($camWidth)x$($camHeight)" -thread_queue_size 1024 -i video="$viddev":audio="$auddev" `
-filter_complex "overlay=main_w-overlay_w-$($screenRes.CurrentHorizontalResolution - $camWidth):main_h-overlay_h-$($screenRes.CurrentVerticalResolution - $camHeight)" `
-movflags +faststart -c:v hevc_qsv -q:v 15 `
"$($env:USERPROFILE)\Videos\$($t.ToString("yyyy-MM-dd_HH-mm-ss"))-desktop-overlay.mp4"
https://ffmpeg.org/ffmpeg-filters.html#overlay-1\\
https://stackoverflow.com/questions/7967699/get-screen-resolution-using-wmi-powershell-in-windows-7
===== Расчёт битрейта для получения точного размера конечного файла =====
# Формула расчёта:
# (([желаемый размер в МБ] * 8kb [перевод в килобиты]) / [кол-во секунд в видео] - [аудиобитрейт]
((200 * 8kb) / 635 -as [int]) - 128 = 2452
& ffmpeg -i "D:\video.mp4" -maxrate 2452k -bufsize 100M -b:a 128k "D:\video200MB.mp4"
https://askubuntu.com/questions/1027340/convert-a-video-by-setting-the-final-size\\
https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate
===== Поиск ключевых кадров =====
& ffprobe -i "D:\Видео\2020-05-21.mp4" -select_streams v -show_frames -show_entries frame=pkt_pts_time,key_frame -sexagesimal -of csv=print_section=0 |
ConvertFrom-Csv -Header key,time |? key -eq 1
https://superuser.com/questions/554620/how-to-get-time-stamp-of-closest-keyframe-before-a-given-timestamp-with-ffmpeg\\
https://superuser.com/questions/885452/extracting-the-index-of-key-frames-from-a-video-using-ffmpeg\\
https://trac.ffmpeg.org/wiki/FFprobeTips
==== Отрезать по ключевому кадру ====
Для этого нужно опцию -ss (начало) указывать до входного видео.
& ffmpeg -ss 5:03 -i .\video.mp4 -c copy .\output.mp4
https://trac.ffmpeg.org/wiki/Seeking\\
https://stackoverflow.com/questions/14005110/how-to-split-a-video-using-ffmpeg-so-that-each-chunk-starts-with-a-key-frame
===== Синхронизация аудио- и видеодорожки =====
Дано: файл, где аудио и видео имеют разную продолжительность, и при пересборке файла начинается рассинхрон.
Input #0, matroska,webm, from '.\2022-04-23_11-39-14_edit.mkv':
Metadata:
ENCODER : Lavf58.20.100
Duration: 00:00:38.74, start: 0.000000, bitrate: 34875 kb/s
Stream #0:0: Video: mjpeg (Baseline), yuvj422p(pc, bt470bg/unknown/unknown), 1280x720, SAR 1
:1 DAR 16:9, 29.97 fps, 29.97 tbr, 1k tbn, 1k tbc (default)
Metadata:
DURATION : 00:00:38.290000000
Stream #0:1: Audio: pcm_s16le, 44100 Hz, 2 channels, s16, 1411 kb/s (default)
Metadata:
DURATION : 00:00:38.743000000
Решение - при пересборке файла учесть разницу:
& ffmpeg -i .\2022-04-23_11-39-14_edit.mkv -ss 00:00:00.453 -i .\2022-04-23_11-39-14_edit1.wav -c copy -shortest '.\2022-04-23_11-39-14_result.mkv'
Если аудио короче видео, то применяется фильтр apad (аудио будет перекодировано):
ffmpeg -i video.mp4 -ss 00:04:00 -i audio.mp3 -c:v copy -af apad -shortest output.mkv
https://stackoverflow.com/questions/13041061/mix-audio-video-of-different-lengths-with-ffmpeg
Если нужно просто сдвинуть одну дорожку относительно другой:
# В этом случае аудио сдвигается вперёд относительно видео.
# Параметр -itsoffset ставится до входного потока, который нужно сдвинуть.
# Входной файл может указываться два раза одинаковый.
ffmpeg -i '.\video.mp4' -itsoffset 00:00:00.600 -i '.\video.mp4' -map 0:v -map 1:a -c copy '.\synced.mp4'
[[https://lzone.de/blog/Easily-fix-async-video-with-ffmpeg|Easily fix async video with ffmpeg]]
===== Прочее, решение проблем =====
==== Об опции -rtbufsize ====
Постоянно был пропуск кадров из-за переполнения буфера:
[dshow @ 000001c9a4bca440] real-time buffer [B525 HD Webcam] [video input] too full or near too full (113% of size: 3041280 [rtbufsize parameter])! frame dropped!
Решение:\\
-rtbufsize 150M (rtbufsize goes before the input name since it applies to inputs)\\
https://stackoverflow.com/questions/45643572/ffmpeg-problems-with-real-time-buffer
==== Too many packets buffered for output stream 0:0 ====
Иногда возникает такая ошибка после запуска кодирования. Помогает опция, её нужно ставить перед выходным файлом:
-max_muxing_queue_size 1024
==== Особенности определения потоков в DVD-Video ====
Неактуально, т. к. нельзя избавиться от первого VOB, где записано меню. Нужно кодировать, собирая нужные файлы:\\
%%ffmpeg -i "concat:VTS_01_1.VOB|VTS_01_2.VOB|VTS_01_3.VOB|и т. д."%%
DVD subtitles may not appear in the first VOB file in a set; it may be necessary to tell ffmpeg to scan ahead deep into the file so that it can find the subtitles in the second VOB file. The directives to do this are -probesize and -analyzeduration – the first being the number of bytes to read ahead into the file, and the second being the number of microseconds (of which there are 1,000,000 per second). These directives must come before the input file directive.
ffmpeg -probesize 1G -analyzeduration 1G -i DVD-Video.iso
https://newspaint.wordpress.com/2016/07/27/ripping-a-video-from-dvd-using-ffmpeg/
==== Quality-based encoding not supported, please specify a bitrate and VBR setting ====
Эта ошибка возникает, когда кодировщик opus принимает на свой счёт опцию ''-global_quality'', предназначенную для видеокодирования через аппаратный QSV. Решение - использовать ''-global_quality:v''.
https://www.reddit.com/r/ffmpeg/comments/12gsvlq/need_help_with_hevc_qsv_and_libopus/
====== Восстановление видео ======
Идея в том, чтобы, кроме битого видео, иметь любое рабочее с того же устройства. Несколько проектов - [[https://github.com/ponchio/untrunc|untrunc]], его форк [[https://github.com/bookkojot/mp4fixer|mp4fixer]].\\
Реальный рабочий вариант, но платный - [[http://grauonline.de/cms2/?page_id=5|Do-It-Yourself Video Repair Tool]] (VRT), Grau GmbH.
====== Популярные разрешения ======
^ 16:9 ^^^
^Ширина ^Высота ^Название ^
|426 |240 |240p (SD) |
|640 |360 |360p (SD), nHD |
|854 |480 |480p (SD) |
|960 |540 |qHD |
|1024 |576 | |
|1280 |720 |720p (HD) |
|1920 |1080 |Full HD |
|2560 |1440 |1440p (2K) |
|3840 |2160 |2160p (4K) |
|7680 |4320 |4320p (8K) |
https://en.wikipedia.org/wiki/16:9_aspect_ratio\\
https://ru.wikipedia.org/wiki/4K_(%D1%80%D0%B0%D0%B7%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B5)
Скрипт расчёта разрешений для разных соотношений сторон для Powershell
# Set ratio here
$w,$h = 16,9
$wInit,$hInit = $w,$h
$report = @()
do {
if ($w%8 -eq 0 -and $h%8 -eq 0) {
$obj = [pscustomobject]@{
Ширина = $w
Высота = $h
}
$report += $obj
}
$w = $w + $wInit
$h = $h + $hInit
} until ($w -gt 7680)
#$report
$report |ConvertTo-Html -Title "$wInit`:$hInit aspect ratio" -PreContent "Соотношение сторон $wInit`:$hInit
" > $env:temp\$wInit-$hInit-aspect-ratio.html
start $env:temp\$wInit-$hInit-aspect-ratio.html
====== Примеры ======
# Взять третью аудиорожку и субтитры из файла в исходной кодировке cp1251,
# отрезать 1:30 в начале файла (заставка), далее оставить 19:35 (до титров),
# закодировать в x264 аппаратно, оставить имя только из цифр.
$files = gci "$env:userprofile\Downloads\Naruto\1 Видео файлы" |? {$_.Extension -eq ".avi" -and $_.basename -ne "Naruto-065 DVDrip"}
$subs = gci "$env:userprofile\Downloads\Naruto\3 Субтитры СРТ" |? Extension -eq ".srt"
foreach ($file in $files) {
$sub = $subs -match $file.basename
& ffmpeg -i $file.fullname -sub_charenc cp1251 -i $sub.fullname `
-map 0:0 -map 0:3 -map 1 -c:a copy -metadata:s:s:0 language=rus `
-c:v h264_qsv -profile:v high -global_quality:v 23 -look_ahead 1 -preset slow `
-ss 00:01:30 -t 00:19:35 `
"$env:userprofile\Videos\$($file.name -replace "\D").mkv" -y
}
# Вариант с заставкой не с начала.
# Аудио нужно перекодировать, субтитры не использовать (неизвестно, как их резать)
foreach ($file in $files) {
$sub = $subs -match $file.basename
& ffmpeg -i $file.fullname -sub_charenc cp1251 -i $sub.fullname `
-filter_complex `
"[0:0]trim=duration=75,setpts=PTS-STARTPTS[av];
[0:2]atrim=duration=75,asetpts=PTS-STARTPTS[aa];
[0:0]trim=start=165:end=1265,setpts=PTS-STARTPTS[bv];
[0:2]atrim=start=165:end=1265,asetpts=PTS-STARTPTS[ba];
[av][bv]concat[outv];[aa][ba]concat=v=0:a=1[outa]" `
-map [outv] -map [outa] -c:a aac `
-c:v h264_qsv -profile:v high -global_quality:v 23 -look_ahead 1 -preset slow `
"$env:userprofile\Videos\$($file.name -replace "\D").mkv" -y
}
====== Заметки ======
https://jellyfin.org/docs/ - Jellyfin is a Free Software Media System that puts you in control of managing and streaming your media\\
https://github.com/bluenviron/mediamtx - RTSP server\\
https://github.com/clsid2/mpc-hc - плеер MPC-HC (форк)\\
https://www.videolan.org/vlc/index.ru.html - плеер VLC