Как в Linux наложить субтитры на видео и ускорить (пример с ffmpeg)

Например, можно наложить субтитры и склеить фрагменты в один видео файл.

Для этой цели можно воспользоваться утилитой ffmpeg (пример для mencoder см. в другой статье), пример:

  • Формат webm:
    ffmpeg -i $f -vf "subtitles=$sub:charenc=utf8:$substyle,$dt,$pts" \
     -af "$atp" -codec:v libvpx -b:v ${webr}k -r $ofps $of
  • Формат x264 (mp4):
    ffmpeg -i $f -vf "subtitles=$sub:charenc=utf8:$substyle,$dt,$pts" \
     -af "$atp" -codec:v libx264 -profile:v baseline -level 3.0 -r $ofps $of

#где:
$f        # исходное видео
$sub      # исходный файл с субтитрами в поддерживаемом формате, тип srt
$substyle # описание стиля субтитров (шрифт, цвет и т.д.)
$dt       # дополнительные параметры наложения текста
$pts      # параметр ускорения
$atp      # дополнительные аудио фильтры ускорения
${webr}   # битрейт для формата webm, например 3600
$ofps     # кол-во кадров в сек., в полученном видеопотоке (после обработки), например 25
$of       # файл, куда сохранять

Пример файла субтитров srt, и соответствие строк:
формат файла субтитров srt

Пример как организовать скрипт на bash для конвертации видео в [webm|mp4] и ускорения, с наложением субтитров и текста

Предварительные параметры можно задать следующим образом:

#Параметры ускорения видеопотока > 1, например в 5 раз: (1/5 = 0.20)
#pts="setpts=0.20*PTS"
speed=5
s=$speed
pts=$(echo "scale=2;1/$speed" | bc -l | sed 's/^\./0\./')
pts=",setpts=$pts*PTS"
 
#Параметры ускорения аудиопотока в 5 раз
#(последовательно применяется фильтр atempo, так что суммарное ускорение = 5.0)
#atp="atempo=2.0,atempo=2.0,atempo=1.0"
atp=""
while [ $speed -ge 2  ]; do
      atp="$atp,atempo=2.0"; speed=$(echo "scale=1;$speed-2" | bc -l)
done
if [ $speed -gt 0 ]; then
      atp="${atp#,},atempo=${speed}.0"
else
      atp="${atp#,}"
fi
 
#Битрейт для webm
webr=3600
 
#Кадров в сек после обработки
ofps=25
 
#Стиль субтитров: шрифт и цвет "00FF00"
substyle="force_style='FontName=CMU Serif Upright Italic,PrimaryColour=&HAA00FF00',"
 
#Наложение текста из файла Text.txt (только на первый видеофрагмент)
# с заданным шрифтом, цветом "00FF00" и прозрачностью "0.3"
# со смещением по оси y как функция от времени t.
dt="drawtext='fontfile=cmunui.otf:textfile=Text.txt:fontcolor=00FF00@0.3:x=(w-text_w)/2:y=h-10*t',"
 
#Источник, каталог
idir=/path_to_input.dir
 
#Назначение, файл.[mp4|webm]
ofile=/path_to_output.file
#временный каталог
odir=${ofile%.*}
test -d "$odir" || { echo "Output dir $odir not found"; mkdir -p $odir; }
 
#Формат mp4 или webm по расширению файла
format=${ofile##*.}
case $format in
        webm) fmt=webm;;
        mp4) fmt=mp4;;
        *) echo "Format $format not supported"; exit 1;;
esac

Итого, в каталоге $idir с видеофайлами *.3gp и субтитрами *.srt будет работать такой цикл:

for f in $idir/*.3gp; do
        fps=$(ffmpeg -i $f 2>&1 | awk -F"," '/Stream.*Video/ {gsub(/[[:space:]]+|fps/,"",$5);print $5}')
        bf=$(basename $f)
        of=$odir/${bf%.3gp}x${s}.$fmt
        test -f "$of" && { echo "File $of exist"; continue; }
        sub=${f%.3gp}.srt
        test -f "$sub" || { echo "File $sub not found"; exit 1; }
        echo "### Convert ###"
        echo "### From $f $fps*$s and sub=$sub"
        echo "### To $of fps=$ofps"
        case $fmt in
             mp4)  ffmpeg -i $f -vf "subtitles=$sub:charenc=utf8:${substyle}${dt}$pts" \
                   -af "$atp" -codec:v libx264 -profile:v baseline -level 3.0 -r $ofps $of;;
             webm) ffmpeg -i $f -vf "subtitles=$sub:charenc=utf8:${substyle}${dt}$pts" \
                   -af "$atp" -codec:v libvpx -b:v ${webr}k -r $ofps $of;;
        esac
        dt=""
done

тут каждый видеофрагмент и соответствующий файл с субтитрами склеивается и ускоряется, полученный видеофрагмент помещается в каталог $odir.

Далее можно видеофрагменты из каталога $odir склеить в файл $odir.$fmt используя функцию concat и список файлов для склейки в виде txt:

#формирую список
fll=""
rm -f ${odir}.txt
for fl in ${odir}/*.$fmt; do
        echo "file ./$fl" >> ${odir}.txt
done
#склеиваю по списку
if [ -f "${odir}.$fmt" ]; then
        echo "### Join skip: File ${odir}.$fmt exist"
else
        echo "### Join to ${odir}.$fmt"
        ffmpeg -f concat -i ${odir}.txt -c copy ${odir}.$fmt
fi
rm -f ${odir}.txt

Для размещения на веб ресурс можно использовать оба формата mp4 и webm, они совместимы с html5 см. http://www.w3schools.com/HTML/html5_video.asp
PS. Видео mp4 в формате h264 с profile=baseline и видео в формате webm можно просматривать на android устройствах.

Пример:

  • Видео в формате webm:
  • Видео в формате mp4:

Обсуждение закрыто.