Как преобразовать файл субтитров из формата .nmea в .srt

Задача

Видеорегистратор формирует фрагменты видео в формате .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

Опции, которые нам могут понадобиться:

  1. В gpsbabel поддержка формата NMEA предполагает возможность читать и записывать точки маршрута (waypoints), читать и записывать треки (tracks). Для работы в режиме чтения треков используем параметр -t
  2. Указать тип файла, параметр: -i INTYPE
  3. Указать исходный файл, параметр: -f INFILE
  4. Применить фильтры, параметр: -x filtername
  5. Указать тип файла для выгрузки, параметр: -o OUTTYPE
  6. Указать файл для выгрузки, параметр: -F OUTFILE

Фильтры, которые могут понадобиться:

  1. Действия с треками (фильтр track): дейсвтие move — коррекция временной метки точек трека (смещением на дельту времени). Зададим так: -x track,move=$timemv
  2. Действия при выгрузке (тип 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»
  3. Формат текста, параметры используемые в примере для 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)

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