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         if [ ! -z ${config[icecast]} ]; then
185                 enableOption input_channel -map %%
186                 enableOption audio_bitrate -ab %%
187                 enableOption channel_name \
188                         -legacy_icecast 1 \
189                         -content_type audio/mpeg \
190                         -ice_name %%
191 
192                 enableOption channel_descr \
193                         -ice_description %%
194 
195                 enableOption icecast \
196                         icecast://source:${config[password]}@${config[icecast]}/${config[mountpoint]}
197         fi
198 
199         # АРХИВ
200         enableOption input_channel -map %%
201         enableOption archive_log \
202                 -segment_list %% \
203                 -segment_list_entry_prefix "${config[archive_dir]}" \
204                 -segment_list_type csv \
205                 -segment_list_flags live
206 
207         # +СЕГМЕНТИРОВАНИЕ
208         enableOption archive_dir \
209                 -segment_atclocktime 1 \
210                 -acodec "${config[output_format]}" \
211                 -fi segment \
212                 -segment_time   "${config[archive_time]}" \
213                 -segment_format "${config[output_format]}" \
214                 -strftime 1     "${config[archive_dir]}/$FILE_NAME"
215 
216         # АНАЛИЗ
217         enableOption input_channel -map %%
218         enableOption slices_log \
219                 -segment_list %% \
220                 -segment_list_entry_prefix "${config[slices_dir]}" \
221                 -segment_list_type csv \
222                 -segment_list_flags live
223 
224         # +СЕГМЕНТИРОВАНИЕ
225         enableOption slices_dir \
226                 -segment_atclocktime 1 \
227                 -acodec "${config[output_format]}" \
228                 -fi segment \
229                 -segment_time   "${config[slices_time]}" \
230                 -segment_format "${config[output_format]}" \
231                 -strftime 1     "${config[slices_dir]}/$FILE_NAME"
232 
233         echo "$CMD"
234 }

streamsaver/config [ Variables ]

[ Top ] [ streamsaver ] [ Variables ]

VARIABLE

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

USED BY

    enableOption, readOption, readXML, makeCMD

SOURCE

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

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>
       <!-- Использование streamproxy -->
       <proxy>1</proxy>
       </xml>

SOURCE

342 SETTINGS="$1"

streamsaver/main [ Toplevel ]

[ Top ] [ streamsaver ] [ Toplevel ]

NAME

    streamsaver

SOURCE

353 #Проверка на наличие файла настроек
354 if [ -z "$SETTINGS" ]; then
355         echo "USAGE: $(basename $0) <settings.xml>" >&2
356         exit 1
357 elif [ ! -r "$SETTINGS" ]; then
358         echo "Unable open file $1." >&2
359         echo "USAGE: $(basename $0) <settings.xml>" >&2
360         exit 1
361 fi
362 
363 #Чтение настроек
364 readXML "$SETTINGS"
365 
366 #Создание директорий хранения файлов, если требуется
367 mkdir -p ${config[archive_dir]}
368 mkdir -p ${config[slices_dir]}
369 
370 if [ ${config[proxy]} == 1 ]; then
371         config[stream]="${config[icecast]}/${config[mountpoint]}"
372         config[icecast]=""
373 fi
374 
375 #Создание команды оцифровки сигнала
376 makeCMD | sh