Задача
Видеорегистратор формирует фрагменты видео в формате .mov и файлы субтитров в формате .nmea. Необходимо выполнить наложение субтитров на видеопоток используя ffmpeg.
Предварительный анализ
В ffmpeg в качестве субтитров можно использовать тип srt (см фильтр subtitles), поэтому попробуем преобразовать файл из .nmea в .srt. А для этого воспользуется утилитой gpsbabel, которая позволяет считывать данные формата NMEA 0183 sentences (nmea) (см. http://www.gpsbabel.org/).
Установка необходимых модулей и создание плана выполнения
Утилита gpsbabel есть во всех популярных дистрибутивах Linux (например — источник epel в CentOS, основной репозиторий в openSUSE и Debian). Ее можно установить из репозитория вашего дистрибутива Linux, либо скачать исходники и собрать самому.
- в CentOS (RedHat) установить: yum install gpsbabel
- в openSUSE (SLES) установить: zypper in gpsbabel
- в Ubuntu (Debian) установить: apt-get install gpsbabel
Установили gpsbabel, а далее разберемся с параметрами
Для начала возьмем наш .nmea файл и попробуем понять что зашифровано в его названии, пример: 20160801_114513.nmea
Можно смело предположить, что в данном случае из названия можно получить дату (20160801) и время (114513).
Теперь рассмотрим утилиту gpsbabel
Опции, которые нам могут понадобиться:
- В gpsbabel поддержка формата NMEA предполагает возможность читать и записывать точки маршрута (waypoints), читать и записывать треки (tracks). Для работы в режиме чтения треков используем параметр -t
- Указать тип файла, параметр: -i INTYPE
- Указать исходный файл, параметр: -f INFILE
- Применить фильтры, параметр: -x filtername
- Указать тип файла для выгрузки, параметр: -o OUTTYPE
- Указать файл для выгрузки, параметр: -F OUTFILE
Фильтры, которые могут понадобиться:
- Действия с треками (фильтр track): дейсвтие move — коррекция временной метки точек трека (смещением на дельту времени). Зададим так: -x track,move=$timemv
- Действия при выгрузке (тип subrip для выгрузки в формат SRT):
- video_time — позиция видеопотока, начиная с которой применимы (т.е. присутствуют) данные GPS. Например, может быть такое, что регистратор начал запись видео, но еще не успел установить связь со спутниками, и данных GPS еще нет
- gps_time — время GPS, соответствующее позиции видео, указанной ранее в параметре video_time
- gps_date — дата GPS, соответствующая позиции видео, указанной ранее в параметре video_time
- format — формат текста, который быдет записан в .srt файл. Зададим так: -o subrip,video_time=000000,gps_time=$gps_time,gps_date=$gps_date,format=»%s km/h $gps_dt %t %e m\n %l»
- Формат текста, параметры используемые в примере для format:
- %s — скорость в км/ч
- %t — отметка времени
- %e — высота в метрах
- \n — перевод строки
- %l — координаты
Обозначим переменные (в примере для bash):
# $gps_dt - дополнительный текст, например дата+время: gps_dt=$(echo $gps_date | sed -r 's/^([0-9]{4})([0-9]{2})([0-9]{2})/\1.\2.\3/') # $srt - файл для выгрузки: srt=20160801_114513.srt # Дельта для действия move timemv=0d2h59m59s # $name - имя исходного файла (nmea) без расширения: name=$(basename ${INFILE%.*}) # $gps_date - дата GPS: gps_date=${name%%_*} # $gps_time - время GPS: gps_time=${name##*_}
в примере выше, timemv определено экспериментальным путем для конкретного регистратора, gps_date и gps_time получаем из имени файла (как условились в самом начале).
Создаем скрипт на bash
Назовем скрипт преобразования файла .nmea в .srt: nmea2srt.sh и соберем все воедино:
#!/bin/bash nmea=$1 srt=$2 name=$(basename ${1%.*}) gps_date=${name%%_*} gps_time=${name##*_} timemv=0d2h59m59s gps_dt=$(echo $gps_date | sed -r 's/^([0-9]{4})([0-9]{2})([0-9]{2})/\1.\2.\3/') gpsbabel -t -i nmea -f $nmea -x track,move=$timemv \ -o subrip,video_time=000000,gps_time=$gps_time,gps_date=$gps_date,format="%s km/h $gps_dt %t %e m\n %l" \ -F $srt
и сделаем его исполняемым:
chmod 755 nmea2srt.sh
здесь имена файлов .nmea и .srt передаются аргументами 1 и 2 соответственно, пример вызова:
./nmea2srt.sh ./20160801_114513.nmea ./20160801_114513.srt
Пример исходного и преобразованного файла
Исходный .nmea:
$GPRMC,084517.00,A,4454.26184,N,03919.84684,E,45.611,115.77,010816,,,A*51 $GPVTG,115.77,T,,M,45.611,N,84.471,K,A*31 $GPGGA,084517.00,4454.26184,N,03919.84684,E,1,10,0.76,38.5,M,21.0,M,,*62 $GPGSA,A,3,12,02,25,06,24,29,19,14,31,05,,,1.23,0.76,0.97*0A $GPGSV,4,1,13,02,61,087,39,05,07,135,34,06,27,047,36,12,76,087,43*73 $GPGSV,4,2,13,14,09,293,22,19,07,065,29,24,23,183,30,25,60,310,38*78 $GPGSV,4,3,13,29,41,259,37,31,11,324,26,32,04,274,23,33,16,244,*7B $GPGSV,4,4,13,40,36,158,*46 $GPGLL,4454.26184,N,03919.84684,E,084517.00,A,A*6A $GSENSOR,20,1004,-100 $GPRMC,084518.00,A,4454.25637,N,03919.86273,E,45.071,116.01,010816,,,A*5E $GPVTG,116.01,T,,M,45.071,N,83.472,K,A*37 $GPGGA,084518.00,4454.25637,N,03919.86273,E,1,10,0.76,38.3,M,21.0,M,,*69 $GPGSA,A,3,12,02,25,06,24,29,19,14,31,05,,,1.23,0.76,0.97*0A $GPGSV,4,1,13,02,61,087,39,05,07,135,29,06,27,047,37,12,76,087,43*7E $GPGSV,4,2,13,14,09,293,22,19,07,065,27,24,23,183,30,25,60,310,38*76 $GPGSV,4,3,13,29,41,259,37,31,11,324,27,32,04,274,23,33,16,244,*7A $GPGSV,4,4,13,40,36,158,*46 $GPGLL,4454.25637,N,03919.86273,E,084518.00,A,A*67 $GSENSOR,98,1034,-124 ...
Преобразованный .srt
1 00:00:03,000 --> 00:00:04,000 84.5 km/h 2016.08.01 11:45:16 - m Lat=44.90437 Lon=39.33079 2 00:00:04,000 --> 00:00:05,000 83.5 km/h 2016.08.01 11:45:17 38 m Lat=44.90437 Lon=39.33079 ...
О том как внедрить субтитры в видео — читай в этой статье:
Как в Linux наложить субтитры на видео и ускорить (пример с ffmpeg)