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

streamsaver/config [ Variables ]

[ Top ] [ streamsaver ] [ Variables ]

VARIABLE

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

USED BY

    enableOption, readOption, readXML, makeCMD

SOURCE

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

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

337 SETTINGS="$1"

streamsaver/main [ Toplevel ]

[ Top ] [ streamsaver ] [ Toplevel ]

NAME

    streamsaver

SOURCE

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