ffmpeg/streamsaver [ Files ]

[ Top ] [ Files ]

NAME

    streamsaver - обработчик аудиопотоков с нарезкой их в файлы и
    ретрансляцией на icecast

VERSION

    1.0

DESCRIPTION

Сценарий принимает аудиопоток с оборудования, по UDP или TCP, фрагментирует его на отрезки заданной длины для последующего хранения и анализа, а также ретранслирует поток на сервер радиовещания icecast для прослушивания аудио конечным пользователем.

USAGE

    streamsaver <файл настроек>

ARGUMENTS


streamsaver/readOption [ Functions ]

[ Top ] [ streamsaver ] [ Functions ]

NAME

    readOption - получение значения опции из файла настроек

USAGE

    readOption <опция> <файл>

ARGUMENTS

RESULT

    Значение параметра при наличии искомой опции в xml-файле или значение по
    умолчанию, которое задаётся при инициализации переменной config.

SOURCE

45 readOption() {
46         cfg=$(\grep -oPm1 "(?<=<$1>)[^<]+" "$2")
47         
48         if [ ! -z "$cfg" ]; then
49                 config[$1]=$cfg
50         fi
51 }

streamsaver/enableOption [ Functions ]

[ Top ] [ streamsaver ] [ Functions ]

NAME

    enableOption - добавление опции к команде ffmpeg

DESCRIPTION

Процедура включает опцию, если в конфигурационном файле имеется соответствующая настройка.

USAGE

    enableOption <опция>

ARGUMENTS

SOURCE

71 enableOption () {
72         if [ ! -z "${config[$1]}" ]; then
73                 CMD+=" $(echo $* | cut -d ' ' -f 2- | sed "s|%%|\"${config[$1]}\"|g")"
74         fi
75 }

streamsaver/readXML [ Functions ]

[ Top ] [ streamsaver ] [ Functions ]

NAME

    readXML - чтение файла настроек

DESCRIPTION

Получение настроек из xml-файла.

USAGE

    readXML <xml>

ARGUMENTS

SOURCE

94 readXML() {
95         #Чтение настроек из файла
96         for option in ${!config[*]}; {
97                 readOption "$option" "$1"
98         }
99 }

streamsaver/makeCMD [ Functions ]

[ Top ] [ streamsaver ] [ Functions ]

NAME

    makeCMD - создание команды для оцифровки сигнала

DESCRIPTION

Процедура составляет команду ffmpeg, включая опции, если они заданы в конфигурационном файле или указаны значения по умолчанию в массиве настроек config.

Эталонные настройки ffmpeg

        ffmpeg  -reconnect 1 \
           \
           -i  "${config[stream]}" \
              -legacy_icecast 1 \
              -content_type audio/mpeg \
              -ice_name "Имя канала" \
              -ice_description "Описание канала" \
              icecast://source:${config[password]}@${config[icecast]}/${config[mountpoint]} \
           \
           -segment_list "./files_archive.csv" \
           -segment_list_entry_prefix "$ARCHIVE_DIR" \
           -segment_list_type "csv" \
           -segment_list_flags "live" \
           -segment_atclocktime 1 \
              -acodec "$FORMAT" -f segment \
              -segment_time   "$ARCHIVE_TIME" \
              -segment_format "$FORMAT" \
              -strftime 1     "$ARCHIVE_DIR/$FILE_NAME"
           \
           -segment_list "./files_slices.csv" \
           -segment_list_entry_prefix "$ARCHIVE_DIR" \
           -segment_list_type "csv" \
           -segment_list_flags "live" \
           -segment_atclocktime 1 \
              -acodec "$FORMAT" -f segment \
              -segment_time   "$SLICES_TIME" \
              -segment_format "$FORMAT" \
              -strftime 1     "$SLICES_DIR/$FILE_NAME"

Пример иерархии файлового хранилища:

        FILES
        ├── archive
        │   ├── TK04
        │   │   └── CH4098
        │   │       └── 2016-07-12_13:41:47-TK#4-4098.mp2
        │   ├── TK05
        │   │   └── CH4098
        │   │       └── 2016-07-12_13:41:45-TK#5-4098.mp2
        │   └── TK06
        │       └── CH53
        │           └── 2016-07-12_13:41:49-TK#6-53.mp2
        └── fragments
            ├── TK04
            │   └── CH4098
            │       ├── 2016-07-12_13:41:47-TK#4-4098.mp2
            │       └── 2016-07-12_13:41:50-TK#4-4098.mp2
            ├── TK05
            │   └── CH4098
            │       ├── 2016-07-12_13:41:45-TK#5-4098.mp2
            │       └── 2016-07-12_13:41:50-TK#5-4098.mp2
            └── TK06
                └── CH53
                    └── 2016-07-12_13:41:49-TK#6-53.mp2

RESULT

    Команда ffmpeg, которую можно передать на выполнение.

SOURCE

173 makeCMD() {
174         #Правило именования файлов
175         FILE_NAME="${config[filename_prefix]}-${config[channel_name]}-CH${config[channel_number]}.${config[filename_suffix]}"
176 
177         #Минимальная команда
178         CMD="${config[cmd]} -f ${config[input_format]} -i ${config[stream]} -f ${config[output_format]}"
179 
180         #КОДИРОВАНИЕ
181         # enableOption output_format -c %%
182 
183         #ICECAST
184         enableOption input_channel -map %%
185         enableOption channel_name \
186                 -legacy_icecast 1 \
187                 -content_type audio/mpeg \
188                 -ice_name %%
189 
190         enableOption channel_descr \
191                 -ice_description %%
192 
193         enableOption icecast \
194                 icecast://source:${config[password]}@${config[icecast]}/${config[mountpoint]}
195 
196         # АРХИВ
197         enableOption input_channel -map %%
198         enableOption archive_log \
199                 -segment_list %% \
200                 -segment_list_entry_prefix "${config[archive_dir]}" \
201                 -segment_list_type csv \
202                 -segment_list_flags live
203 
204         # +СЕГМЕНТИРОВАНИЕ
205         enableOption archive_dir \
206                 -segment_atclocktime 1 \
207                 -acodec "${config[output_format]}" \
208                 -fi segment \
209                 -segment_time   "${config[archive_time]}" \
210                 -segment_format "${config[output_format]}" \
211                 -strftime 1     "${config[archive_dir]}/$FILE_NAME"
212 
213         # АНАЛИЗ
214         enableOption input_channel -map %%
215         enableOption slices_log \
216                 -segment_list %% \
217                 -segment_list_entry_prefix "${config[slices_dir]}" \
218                 -segment_list_type csv \
219                 -segment_list_flags live
220 
221         # +СЕГМЕНТИРОВАНИЕ
222         enableOption slices_dir \
223                 -segment_atclocktime 1 \
224                 -acodec "${config[output_format]}" \
225                 -fi segment \
226                 -segment_time   "${config[slices_time]}" \
227                 -segment_format "${config[output_format]}" \
228                 -strftime 1     "${config[slices_dir]}/$FILE_NAME"
229 
230         echo "$CMD"
231 }

streamsaver/config [ Variables ]

[ Top ] [ streamsaver ] [ Variables ]

VARIABLE

    config - массив настроек, содержащий значения по-умолчанию.
    Настройки описаны в секции SETTINGS.

USED BY

    enableOption, readOption, readXML, makeCMD

SOURCE

247 typeset -A config
248 
249 config=(
250         [stream]=""
251         [icecast]=""
252         [password]=""
253         [channel_name]=""
254         [channel_number]=""
255         [channel_descr]=""
256         [mountpoint]=""
257         [cmd]="ffmpeg"
258         [input_format]="mpegts"
259         [input_channel]=""
260         [archive_dir]=""
261         [archive_time]=""
262         [archive_log]=""
263         [slices_dir]=""
264         [slices_time]=""
265         [slices_log]=""
266         [filename_prefix]="%Y-%m-%d_%H:%M:%S"
267         [filename_suffix]="mp2"
268         [output_format]="mp2"
269         [audio_bitrate]="256k"
270 )

streamsaver/SETTINGS [ Variables ]

[ Top ] [ streamsaver ] [ Variables ]

VARIABLE

    SETTINGS - файл настроек

DESCRIPTION

Переменная хранит имя файла настроек, который содержит параметры, перечисленные в массиве опций config, в формате XML. При отсутствии параметра или пустом значении соответствующие флаги а аргументы не добавляются в итоговую команду ffmpeg. Таким образом, например, можно включать или отключать ведение журнала сохранения аудиозаписей, просто указывая или удаляя параметр archive_log.

Формат файла настроек следующий:

       <xml>
       <!-- Название канала -->
       <channel_name></channel_name>
       <!-- Описание канала -->
       <channel_descr>Тестовый_канал</channel_descr>
       <!-- Входящий поток  -->
       <stream>http://localhost:8000/tuc01
       <!-- Icecast для вывода -->
       <icecast>localhost:8000</icecast>
       <!-- Пароль для доступа к Icecast -->
       <password>hackme</password>
       <!-- Точка подключения канала -->
       <mountpoint>tuc02</mountpoint>
       <!-- Программа/канал из потока -->
       <input_channel>0:p:4098</input_channel>

       <!-- Команда получения сигнала -->
       <cmd>ffmpeg</cmd>

       <!-- Формат входного потока -->
       <input_format>mp2 -map 0:0</input_format>

       <!-- Директория для сохранения архивных файлов -->
       <archive_dir>FILES/archive/</archive_dir>
       <!-- Длительность архивных файлов в секундах -->
       <archive_time>3600</archive_time>
       <!-- Файл журнала обработки архивных записей -->
       <archive_log>FILES/archive.log</archive_log>

       <!-- Директория для сохранения фрагментов на анализ -->
       <slices_dir>FILES/fragments/</slices_dir>
       <!-- Длительность фрагментов для анализа в секундах -->
       <slices_time>10</slices_time>
       <!-- Файл журнала обработки фрагментов на анализ -->
       <slices_log>FILES/fragments.log</slices_log>

       <!-- Префикс имени файла -->
       <filename_prefix>%Y-%m-%d_%H:%M:%S</filename_prefix>
       <!-- Расширение имени файла -->
       <filename_suffix>mp2</filename_suffix>

       <!-- Формат аудиофайлов -->
       <output_format>mp2</output_format>
       <!-- Битрейт аудиофайлов -->
       <audio_bitrate>256k</audio_bitrate>
       </xml>

SOURCE

336 SETTINGS="$1"

streamsaver/main [ Toplevel ]

[ Top ] [ streamsaver ] [ Toplevel ]

NAME

    streamsaver

SOURCE

347 #Проверка на наличие файла настроек
348 if [ -z "$SETTINGS" ]; then
349         echo "USAGE: $(basename $0) <settings.xml>" >&2
350         exit 1
351 elif [ ! -r "$SETTINGS" ]; then
352         echo "Unable open file $1." >&2
353         echo "USAGE: $(basename $0) <settings.xml>" >&2
354         exit 1
355 fi
356 
357 #Чтение настроек
358 readXML "$SETTINGS"
359 
360 #Создание директорий хранения файлов, если требуется
361 mkdir -p ${config[archive_dir]}
362 mkdir -p ${config[slices_dir]}
363 
364 #Создание команды оцифровки сигнала
365 makeCMD