Решил выложить для истории творение в дождливые майские выходные. А началось все с мысли
«пойду-ка включу свой NAS и скину на него фото и видео с телефона и найду еще пару фоток»
Накопилась на домашнем NAS DLink-327L куча видео со старых Sony камеры и фотоаппарата. Столкнулся с тем, что видео в формате MPEG-PS не читаются на Android-е без костылей и пересжатия.
Решил перекодировать все в mp4 кодеком h264.
Что имеем на входе:
- девайс NAS DLink-327L + Samba shared
- Ноут с Win10 Home + WSL Debian (для задействования bash-скрипта) - вот такое вот извращение))
Все далее делаем только на ноуте.
Монтируем сетевой диск R: на ноут и следом монтируем его в Debian, но помним, что это WSL-версия Debian
sudo mount -t drvfs "r:" /mnt/photo
drvfs - хитрость именно тут
Исходный формат через команду mediainfo MOV07549.MPG выдал:
General
Complete name : MOV07549.MPG
Format : MPEG-PS
File size : 44.2 MiB
Duration : 35 s 424 ms
Overall bit rate mode : Variable
Overall bit rate : 10.5 Mb/s
Video
ID : 224 (0xE0)
Format : MPEG Video
Format version : Version 1
Format settings, BVOP : No
Format settings, Matrix : Default
Format settings, GOP : N=1
Duration : 35 s 400 ms
Bit rate mode : Variable
Bit rate : 10.2 Mb/s
Width : 640 pixels
Height : 480 pixels
Display aspect ratio : 4:3
Frame rate : 30.000 FPS
Color space : YUV
Chroma subsampling : 4:2:0
Bit depth : 8 bits
Scan type : Progressive
Compression mode : Lossy
Bits/(Pixel*Frame) : 1.107
Time code of first frame : 00:00:00:00
Time code source : Group of pictures header
GOP, Open/Closed : Closed
Stream size : 43.0 MiB (97%)
Audio
ID : 192 (0xC0)
Format : MPEG Audio
Format version : Version 1
Format profile : Layer 2
Duration : 35 s 424 ms
Bit rate mode : Constant
Bit rate : 64.0 kb/s
Channel(s) : 1 channel
Sampling rate : 32.0 kHz
Compression mode : Lossy
Stream size : 277 KiB (1%)
Конвертирование в mp4 кодеком libx264 тулзой ffmpeg
Пишем скрипт на bash convertpmg.sh для обхода всего каталога смонтированного в /mnt/photo:
#!/bin/bash
tmpIFS=$IFS; IFS=$'\n'
for file in `find /mnt/photo -type f -iname "*.MPG"`; do
# выводим что нашли для обработки
echo $file
# меняем только расширение файла на .mp4 и оставляем тот же путь
mp4=$(echo $file | sed 's/.MPG/.mp4/g')
# echo "$mp4"
# делаем проверку если файл еще не конвертировали ранее
if [ ! -f "$mp4" ]; then
ffmpeg -i "$file" -f mp4 -vf "yadif=0:-1:0,hqdn3d" -c:v libx264 -crf 18 -preset slow -threads 6 "$mp4"
fi
done
IFS=$tmpIFS
Небольшие пояснения:
Используем хак bash для "неправильных" названий каталогов типа "Новый год", "23 февраля", т.е. там где есть пробелы или дефис и т.п. символы
tmpIFS=$IFS; IFS=$'\n'
...
IFS=$tmpIFS
Основной код конвертации через ffmpeg
ffmpeg -i "$file" -f mp4 -vf "yadif=0:-1:0,hqdn3d" -c:v libx264 -crf 18 \
-preset slow -threads 6 "$mp4"
основной параметр, который дал приемлемое качество на выходе
-vf "yadif=0:-1:0,hqdn3d"
но можно просто:
-vf yadif
и
-crf 18
это дает неразличимое глазу сжатие
Как видим, кодируем только видео поток, остальное оставляем по умолчанию на действие параметра
-preset slow
и желаемый на выходе кодек:
-c:v libx264
кодируем 6 потоками (поставил на ночь и забыл):
-threads 6
Замена времени создания, редактирования и доступа силами PowerShell
Далее интереснее - в linux беда с подделкой времени создания файла, поэтому погуглив пришел к тому, что проще на ноуте использовать PowerShell.
После прохода нашим bash-скриптом:
bash -C convertpmg.sh
в каталоге с *.MPG файлами появились *.mp4 файлы и теперь им надо установить такие же даты (это важно для дальнейшего построения галереи по календарю) как у *.MPG.
Пишем файл PowerShell-скрипт updatetime.ps1
$Directory = "r:"
# скрипт устанавливает дату создания, изменения и доступа
# для mp4 файлов как у MPG файлов
foreach ($file in (Get-ChildItem -Path $Directory -Recurse -Filter *.MPG)){
$fullName = $file.FullName.ToString().Replace( ".MPG", ".mp4")
# делаем проверку на существование mp4-файла
if(Test-Path $fullName -PathType Leaf){
$mp4File = (Get-Item -Path $fullName)
$mp4File.CreationTime = $file.CreationTime
$mp4File.LastAccessTime = $file.LastAccessTime
$mp4File.LastWriteTime = $file.LastWriteTime
# печатаем что обработали
$fullName
}
}
Заметка файл updatetime.ps1 запускать с локального диска, a не с shared samba - R:
Теперь осталось почистить исходные MPG, удалив их с диска (если они больше не нужны ... совсем... никогда :) )
Пишем на bash такой скрипт removeMPG.sh :
#!/bin/bash
# удалить исходник несжатого видео при наличии сжатой копии
tmpIFS=$IFS; IFS=$'\n'
for file in find /mnt/photo -type f -iname "*.MPG"; do
mp4=$(echo $file | sed 's/.MPG/.mp4/g')
if [ -f $mp4 ]; then
echo $file
rm $file
fi
done
IFS=$tmpIFS
для bash критично использование регистра MPG и mpg это разные файлы, поэтому про это тоже помним ))
Вызываем:
bash -C removeMPG.sh
и слезно плачем по безвозвратно удаленным файлам...
Смотрим что теперь выдает mediainfo для сконвертированного mp4 файла:
General
Complete name : MOV07549.mp4
Format : MPEG-4
Format profile : Base Media
Codec ID : isom (isom/iso2/avc1/mp41)
File size : 20.7 MiB
Duration : 35 s 456 ms
Overall bit rate : 4 887 kb/s
Encoded date : UTC 1904-01-01 00:00:00
Tagged date : UTC 1904-01-01 00:00:00
Writing application : Lavf57.56.101
Video
ID : 1
Format : AVC
Format/Info : Advanced Video Codec
Format profile : High@L3
Format settings, CABAC : Yes
Format settings, ReFrames : 5 frames
Codec ID : avc1
Codec ID/Info : Advanced Video Coding
Duration : 35 s 400 ms
Bit rate : 4 819 kb/s
Width : 640 pixels
Height : 480 pixels
Display aspect ratio : 4:3
Frame rate mode : Constant
Frame rate : 30.000 FPS
Color space : YUV
Chroma subsampling : 4:2:0
Bit depth : 8 bits
Scan type : Progressive
Bits/(Pixel*Frame) : 0.523
Stream size : 20.3 MiB (98%)
Writing library : x264 core 148 r2748 97eaef2
Encoding settings : cabac=1 / ref=5 / deblock=1:0:0 / analyse=0x3:0x113 / me=hex / subme=8 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=2 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=6 / lookahead_threads=1 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=2 / b_adapt=1 / b_bias=0 / direct=3 / weightb=1 / open_gop=0 / weightp=2 / keyint=250 / keyint_min=25 / scenecut=40 / intra_refresh=0 / rc_lookahead=50 / rc=crf / mbtree=1 / crf=18.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / ip_ratio=1.40 / aq=1:1.00
Encoded date : UTC 1904-01-01 00:00:00
Tagged date : UTC 1904-01-01 00:00:00
Audio
ID : 2
Format : AAC
Format/Info : Advanced Audio Codec
Format profile : LC
Codec ID : 40
Duration : 35 s 456 ms
Bit rate mode : Constant
Bit rate : 69.4 kb/s
Channel(s) : 2 channels
Channel(s)_Original : 1 channel
Channel positions : Front: C
Sampling rate : 32.0 kHz
Frame rate : 31.250 FPS (1024 spf)
Compression mode : Lossy
Stream size : 300 KiB (1%)
Default : Yes
Alternate group : 1
Encoded date : UTC 1904-01-01 00:00:00
Tagged date : UTC 1904-01-01 00:00:00
И вот собственно все!
Хотя нет...
Забыл что есть еще DVD видео 3-4 диска на NAS, тут уже руками можно ))
Из текущего каталога VIDEO_TS в bash вызываем:
cat VTS0**VOB | ffmpeg -i - -f mp4 -vf "yadif=0:-1:0,hqdn3d" -c:v libx264 -crf 18 -preset slow -threads 6 filenameXXX.mp4
P.S. Все писалось для себя, чтобы не забыть как и что делал и может это кому-то пригодится еще.
Если бы знал все про подводные камни с монтированием диска WSL Debian, про траблы с неправильными именами директорий, то сразу бы сделал все на PowerShell, используя консольный вариант ffmpeg для windows. Может кто предложит в комментах другие варианты.
P.P.S. Дзен, что не умеет офрмлять программный код и выделять примечания?
Оригинал этой же статьи на (с) Jen - teletype.in