From 8cddc04f4c4da91c4fb9a2a0d1a988b3feaae39b Mon Sep 17 00:00:00 2001 From: Maxim Lihachev Date: Tue, 12 Jul 2016 14:45:01 +0500 Subject: [PATCH] streamsaver + settings + docs --- doc/masterindex.html | 47 ++++++ doc/robo_files.html | 39 +++++ doc/robo_functions.html | 42 +++++ doc/robo_sourcefiles.html | 44 +++++ doc/robo_variables.html | 40 +++++ doc/robodoc.css | 302 ++++++++++++++++++++++++++++++++++ doc/streamsaver.html | 407 ++++++++++++++++++++++++++++++++++++++++++++++ doc/tobo_toplevel.html | 39 +++++ doc/toc_index.html | 48 ++++++ robodoc.rc | 166 +++++++++++++++++++ settings.xml | 45 +++++ streamsaver | 337 ++++++++++++++++++++++++++++++++++++++ 12 files changed, 1556 insertions(+) create mode 100644 doc/masterindex.html create mode 100644 doc/robo_files.html create mode 100644 doc/robo_functions.html create mode 100644 doc/robo_sourcefiles.html create mode 100644 doc/robo_variables.html create mode 100644 doc/robodoc.css create mode 100644 doc/streamsaver.html create mode 100644 doc/tobo_toplevel.html create mode 100644 doc/toc_index.html create mode 100644 robodoc.rc create mode 100644 settings.xml create mode 100755 streamsaver diff --git a/doc/masterindex.html b/doc/masterindex.html new file mode 100644 index 0000000..d893e89 --- /dev/null +++ b/doc/masterindex.html @@ -0,0 +1,47 @@ + + + + + + + +Index + + + + + +
+
+ +
+

Index

+

A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

+

C

config +

E

enableOption +

M

main +makeCMD +

R

readOption +readXML +

S

SETTINGS +streamsaver +streamsaver +

A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

+
+ + + diff --git a/doc/robo_files.html b/doc/robo_files.html new file mode 100644 index 0000000..4020bad --- /dev/null +++ b/doc/robo_files.html @@ -0,0 +1,39 @@ + + + + + + + +Files + + + + + +
+
+ +
+

Files

+

A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

+

S

streamsaver +

A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

+
+ + + diff --git a/doc/robo_functions.html b/doc/robo_functions.html new file mode 100644 index 0000000..da0bc33 --- /dev/null +++ b/doc/robo_functions.html @@ -0,0 +1,42 @@ + + + + + + + +Functions + + + + + +
+
+ +
+

Functions

+

A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

+

E

enableOption +

M

makeCMD +

R

readOption +readXML +

A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

+
+ + + diff --git a/doc/robo_sourcefiles.html b/doc/robo_sourcefiles.html new file mode 100644 index 0000000..07cb4c3 --- /dev/null +++ b/doc/robo_sourcefiles.html @@ -0,0 +1,44 @@ + + + + + + + +Sourcefiles + + + + + +
+
+ +
+ +
+ + + diff --git a/doc/robo_variables.html b/doc/robo_variables.html new file mode 100644 index 0000000..72f828a --- /dev/null +++ b/doc/robo_variables.html @@ -0,0 +1,40 @@ + + + + + + + +Variables + + + + + +
+
+ +
+

Variables

+

A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

+

C

config +

S

SETTINGS +

A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

+
+ + + diff --git a/doc/robodoc.css b/doc/robodoc.css new file mode 100644 index 0000000..207a172 --- /dev/null +++ b/doc/robodoc.css @@ -0,0 +1,302 @@ +/****h* ROBODoc/ROBODoc Cascading Style Sheet + * FUNCTION + * This is the default cascading style sheet for documentation + * generated with ROBODoc. + * You can edit this file to your own liking and then use + * it with the option + * --css + * + * This style-sheet defines the following layout + * +----------------------------------------+ + * | logo | + * +----------------------------------------+ + * | extra | + * +----------------------------------------+ + * | | navi- | + * | | gation | + * | content | | + * | | | + * +----------------------------------------+ + * | footer | + * +----------------------------------------+ + * + * This style-sheet is based on a style-sheet that was automatically + * generated with the Strange Banana stylesheet generator. + * See http://www.strangebanana.com/generator.aspx + * + ****** + * $Id: html_generator.c,v 1.94 2008/06/17 11:49:27 gumpu Exp $ + */ + +body +{ + background-color: rgb(255,255,255); + color: rgb(98,84,55); + font-family: Arial, serif; + border-color: rgb(226,199,143); +} + +pre +{ + font-family: monospace; + margin: 15px; + padding: 5px; + white-space: pre; + color: #000; +} + +pre.source +{ + background-color: #ffe; + border: dashed #aa9 1px; +} + +p +{ + margin:15px; +} + +p.item_name +{ + font-weight: bolder; + margin:5px; + font-size: 120%; +} + +#content +{ + font-size: 100%; + color: rgb(0,0,0); + background-color: rgb(255,255,255); + border-left-width: 0px; + border-right-width: 0px; + border-top-width: 0px; + border-bottom-width: 0px; + border-left-style: none; + border-right-style: none; + border-top-style: none; + border-bottom-style: none; + padding: 40px 31px 14px 17px; + border-color: rgb(0,0,0); + text-align: justify; +} + +#navigation +{ + background-color: rgb(98,84,55); + color: rgb(230,221,202); + font-family: "Times New Roman", serif; + font-style: normal; + border-color: rgb(0,0,0); +} + +a.menuitem +{ + font-size: 120%; + background-color: rgb(0,0,0); + color: rgb(195,165,100); + font-variant: normal; + text-transform: none; + font-weight: normal; + padding: 1px 8px 3px 1px; + margin-left: 5px; + margin-right: 5px; + margin-top: 5px; + margin-bottom: 5px; + border-color: rgb(159,126,57); + text-align: right; +} + +#logo, #logo a +{ + font-size: 130%; + background-color: rgb(198,178,135); + color: rgb(98,84,55); + font-family: Georgia, serif; + font-style: normal; + font-variant: normal; + text-transform: none; + font-weight: bold; + padding: 20px 18px 20px 18px; + border-color: rgb(255,255,255); + text-align: right; +} + +#extra, #extra a +{ + font-size: 128%; + background-color: rgb(0,0,0); + color: rgb(230,221,202); + font-style: normal; + font-variant: normal; + text-transform: none; + font-weight: normal; + border-left-width: 0px; + border-right-width: 0px; + border-top-width: 0px; + border-bottom-width: 0px; + border-left-style: none; + border-right-style: none; + border-top-style: none; + border-bottom-style: none; + padding: 12px 12px 12px 12px; + border-color: rgb(195,165,100); + text-align: center; +} + +#content a +{ + color: rgb(159,126,57); + text-decoration: none; +} + +#content a:hover, #content a:active +{ + color: rgb(255,255,255); + background-color: rgb(159,126,57); +} + +a.indexitem +{ + display: block; +} + +h1, h2, h3, h4, h5, h6 +{ + background-color: rgb(221,221,221); + font-family: Arial, serif; + font-style: normal; + font-variant: normal; + text-transform: none; + font-weight: normal; +} + +h1 +{ + font-size: 151%; +} + +h2 +{ + font-size: 142%; +} + +h3 +{ + font-size: 133%; +} + +h4 +{ + font-size: 124%; +} + +h5 +{ + font-size: 115%; +} + +h6 +{ + font-size: 106%; +} + +#navigation a +{ + text-decoration: none; +} + +.menuitem:hover +{ + background-color: rgb(195,165,100); + color: rgb(0,0,0); +} + +#extra a +{ + text-decoration: none; +} + +#logo a +{ + text-decoration: none; +} + +#extra a:hover +{ +} + +/* layout */ +#navigation +{ + width: 22%; + position: relative; + top: 0; + right: 0; + float: right; + text-align: center; + margin-left: 10px; +} + +.menuitem {width: auto;} +#content {width: auto;} +.menuitem {display: block;} + + +div#footer +{ + background-color: rgb(198,178,135); + color: rgb(98,84,55); + clear: left; + width: 100%; + font-size: 71%; +} + +div#footer a +{ + background-color: rgb(198,178,135); + color: rgb(98,84,55); +} + +div#footer p +{ + margin:0; + padding:5px 10px +} + +span.keyword +{ + color: #00F; +} + +span.comment +{ + color: #080; +} + +span.quote +{ + color: #F00; +} + +span.squote +{ + color: #F0F; +} + +span.sign +{ + color: #008B8B; +} + +span.line_number +{ + color: #808080; +} + +@media print +{ + #navigation {display: none;} + #content {padding: 0px;} + #content a {text-decoration: underline;} +} diff --git a/doc/streamsaver.html b/doc/streamsaver.html new file mode 100644 index 0000000..ff0ecfc --- /dev/null +++ b/doc/streamsaver.html @@ -0,0 +1,407 @@ + + + + + + + +./streamsaver + + + + + + +
+
+ +

ffmpeg/streamsaver [ Files ]

+ +

[ Top ] [ Files ]

+

NAME

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

VERSION

+
    1.0
+
+

DESCRIPTION

+

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

+

USAGE

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

ARGUMENTS

+
  • <файл настроек> - xml-файл с описанием входящего и выходящего потоков и + правилами фрагментирования записей. +
  • +
+

+ +
+ +

streamsaver/readOption [ Functions ]

+ +

[ Top ] [ streamsaver ] [ Functions ]

+

NAME

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

USAGE

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

ARGUMENTS

+
  • опция - имя опции +
  • +
  • файл - xml-файл с настройками +
  • +
+

+

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

+
  • опция - имя опции из массива настроек config. +
  • +
+

+

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

+
  • xml - файл настроек. +
  • +
+

+

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" -map 0  -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" -map 0  -f segment \
+              -segment_time   "$SLICES_TIME" \
+              -segment_format "$FORMAT" \
+              -strftime 1     "$SLICES_DIR/$FILE_NAME"
+
+

+

RESULT

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

SOURCE

+
148 makeCMD() {
+149         #Правило именования файлов
+150         FILE_NAME="${config[filename_prefix]}-${config[channel_name]}.${config[filename_suffix]}"
+151 
+152         #Минимальная команда
+153         CMD="${config[cmd]} -reconnect 1 -i ${config[stream]} -f mp2"
+154         # " -f ${config[input_format]}"
+155 
+156         #КОДИРОВАНИЕ
+157         # enableOption output_format -c %%
+158 
+159         #ICECAST
+160         enableOption channel_name \
+161                 -legacy_icecast 1 \
+162                 -content_type audio/mpeg \
+163                 -ice_name %%
+164 
+165         enableOption channel_descr \
+166                 -ice_description %%
+167 
+168         enableOption icecast \
+169                 icecast://source:${config[password]}@${config[icecast]}/${config[mountpoint]}
+170 
+171         # АРХИВ
+172         enableOption archive_log \
+173                 -segment_list %% \
+174                 -segment_list_entry_prefix "${config[archive_dir]}" \
+175                 -segment_list_type csv \
+176                 -segment_list_flags live
+177 
+178         # +СЕГМЕНТИРОВАНИЕ
+179         enableOption archive_dir \
+180                 -segment_atclocktime 1 \
+181                 -acodec "${config[output_format]}" -map 0 \
+182                 -fi segment \
+183                 -segment_time   "${config[archive_time]}" \
+184                 -segment_format "${config[output_format]}" \
+185                 -strftime 1     "${config[archive_dir]}/$FILE_NAME"
+186 
+187         # АНАЛИЗ
+188         enableOption slices_log \
+189                 -segment_list %% \
+190                 -segment_list_entry_prefix "${config[slices_dir]}" \
+191                 -segment_list_type csv \
+192                 -segment_list_flags live
+193 
+194         # +СЕГМЕНТИРОВАНИЕ
+195         enableOption slices_dir \
+196                 -segment_atclocktime 1 \
+197                 -acodec "${config[output_format]}" -map 0 \
+198                 -fi segment \
+199                 -segment_time   "${config[slices_time]}" \
+200                 -segment_format "${config[output_format]}" \
+201                 -strftime 1     "${config[slices_dir]}/$FILE_NAME"
+202 
+203         echo "$CMD"
+204 }
+
+ +
+ +

streamsaver/config [ Variables ]

+ +

[ Top ] [ streamsaver ] [ Variables ]

+

VARIABLE

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

USED BY

+
    enableOption, readOption, readXML, makeCMD
+
+

SOURCE

+
220 typeset -A config
+221 
+222 config=(
+223         [stream]=""
+224         [icecast]="http://localhost:8000/"
+225         [password]="hackme"
+226         [channel_name]=""
+227         [channel_descr]=""
+228         [mountpoint]=""
+229         [cmd]="ffmpeg"
+230         [input_format]="mpegts"
+231         [archive_dir]=""
+232         [archive_time]="3600"
+233         [archive_log]="/var/log/tuc01_archive.log"
+234         [slices_dir]=""
+235         [slices_time]=10
+236         [slices_log]="/var/log/tuc01_slices.log"
+237         [filename_prefix]="%Y-%m-%d_%H:%M:%S"
+238         [filename_suffix]="mp2"
+239         [output_format]="mp2"
+240         [audio_bitrate]="256k"
+241 )
+
+ +
+ +

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>
+
+

+

+
       <!-- Команда получения сигнала -->
+       <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

+
305 SETTINGS="$1"
+
+ +
+ +

streamsaver/main [ Toplevel ]

+ +

[ Top ] [ streamsaver ] [ Toplevel ]

+

NAME

+
    streamsaver
+
+

SOURCE

+
316 #Проверка на наличие файла настроек
+317 if [ -z "$SETTINGS" ]; then
+318         echo "USAGE: $(basename $0) <settings.xml>" >&2
+319         exit 1
+320 elif [ ! -r "$SETTINGS" ]; then
+321         echo "Unable open file $1." >&2
+322         echo "USAGE: $(basename $0) <settings.xml>" >&2
+323         exit 1
+324 fi
+325 
+326 #Чтение настроек
+327 readXML "$SETTINGS"
+328 
+329 #Создание директорий хранения файлов, если требуется
+330 mkdir -p ${config[archive_dir]}
+331 mkdir -p ${config[slices_dir]}
+332 
+333 #Создание команды оцифровки сигнала
+334 makeCMD
+
+ +
+ + + diff --git a/doc/tobo_toplevel.html b/doc/tobo_toplevel.html new file mode 100644 index 0000000..400214a --- /dev/null +++ b/doc/tobo_toplevel.html @@ -0,0 +1,39 @@ + + + + + + + +Toplevel + + + + + +
+
+ +
+

Toplevel

+

A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

+

M

main +

A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

+
+ + + diff --git a/doc/toc_index.html b/doc/toc_index.html new file mode 100644 index 0000000..c865f56 --- /dev/null +++ b/doc/toc_index.html @@ -0,0 +1,48 @@ + + + + + + + +Table of Contents + + + + + +
+
+ + + + + diff --git a/robodoc.rc b/robodoc.rc new file mode 100644 index 0000000..8947c9b --- /dev/null +++ b/robodoc.rc @@ -0,0 +1,166 @@ +items: +# +# CUSTOM +# + DATA + DEFAULT VALUE + GUI + INIT VALUE + NAMESPACE + PACKAGES + RESOURCE + STRUCTURE + USED GLOBAL VARIABLES + USED VARIABLES + USER HELP + VARIABLE + VARIABLES + VERSION +# +# DEFAULT +# + ARGUMENTS + ATTRIBUTES + AUTHOR + BUGS + CHILDREN + COMMANDS + COPYRIGHT + CREATION DATE + DERIVED BY + DERIVED FROM + DESCRIPTION + DIAGNOSTICS + ERRORS + EXAMPLE + FUNCTION + HISTORY + IDEAS + INPUTS + METHODS + MODIFICATION HISTORY + NAME + NEW ATTRIBUTES + NEW METHODS + NOTES + OPTIONS + OUTPUT + PARAMETERS + PARENTS + PORTABILITY + PURPOSE + RESULT + RETURN VALUE + SEE ALSO + SIDE EFFECTS + SOURCE + SWITCHES + SYNOPSIS + TAGS + TODO + USAGE + USED BY + USES + WARNINGS +ignore items: +item order: + FUNCTION + SYNOPSIS + INPUTS +source items: + SOURCE + DATA +preformatted items: + INPUTS +format items: + PORTABILITY + FUNCTION + DESCRIPTION + ARGUMENTS + PACKAGES + USED GLOBAL VARIABLES + USED VARIABLES + NOTES + VARIABLES + NAMESPACE + BUGS + TODO +options: + --src . + --doc ./doc + --html + --multidoc + --charset utf-8 + --nosort + --sections + --source_line_numbers + --index + --tabsize 8 + --syntaxcolors_enable quotes,squotes,line_comments,block_comments,keywords,non_alpha +headertypes: + F Files robo_files + a Aliases robo_aliases + I Interpretators robo_interps + p Packages robo_packages + G "Global variables" robo_globals + n Namespaces robo_namespaces + r Resources robo_resources + c "Control flow structures" robo_control_structures + t Toplevel tobo_toplevel +ignore files: + README + CVS + robodoc.rc + config + *.xml + *.bak + *.git + *~ +accept files: + streamsaver +header markers: + #**** +remark markers: + # +end markers: + #**** +header separate characters: + , +header ignore characters: + [ + ] + # +remark begin markers: +remark end markers: +source line comments: + # +keywords: + if + then + else + elif + fi + case + esac + for + select + while + until + do + done + in + function + time + { + } + ! + [[ + ]] + coproc + echo + ffmpeg + mkdir + grep + exit + typeset + diff --git a/settings.xml b/settings.xml new file mode 100644 index 0000000..2d93c23 --- /dev/null +++ b/settings.xml @@ -0,0 +1,45 @@ + + + RT + + Тестовый_канал_RT + + http://localhost:8000/tuc01 + + localhost:8000 + + hackme + + rt + + + ffmpeg + + + mp2 -map 0:0 + + + FILES/archive/ + + 3600 + + FILES/archive.log + + + FILES/fragments/ + + 10 + + FILES/fragments.log + + + %Y-%m-%d_%H:%M:%S + + mp2 + + + mp2 + + 256k + + diff --git a/streamsaver b/streamsaver new file mode 100755 index 0000000..93e7603 --- /dev/null +++ b/streamsaver @@ -0,0 +1,337 @@ +#!/bin/bash + +#****F* ffmpeg/streamsaver **************************************************** +# +# NAME +# streamsaver - обработчик аудиопотоков с нарезкой их в файлы и +# ретрансляцией на icecast +# +# VERSION +# 1.0 +# +# DESCRIPTION +# Сценарий принимает аудиопоток с оборудования, по UDP или TCP, +# фрагментирует его на отрезки заданной длины для последующего хранения и +# анализа, а также ретранслирует поток на сервер радиовещания icecast для +# прослушивания аудио конечным пользователем. +# +# USAGE +# streamsaver <файл настроек> +# +# ARGUMENTS +# * <файл настроек> - xml-файл с описанием входящего и выходящего потоков и +# правилами фрагментирования записей. +# +#****************************************************************************** + +#****f* streamsaver/readOption +# +# NAME +# readOption - получение значения опции из файла настроек +# +# USAGE +# readOption <опция> <файл> +# +# ARGUMENTS +# * опция - имя опции +# * файл - xml-файл с настройками +# +# RESULT +# Значение параметра при наличии искомой опции в xml-файле или значение по +# умолчанию, которое задаётся при инициализации переменной config. +# +# SOURCE +# +readOption() { + cfg=$(\grep -oPm1 "(?<=<$1>)[^<]+" "$2") + + if [ ! -z "$cfg" ]; then + config[$1]=$cfg + fi +} +#***** + +#****f* streamsaver/enableOption +# +# NAME +# enableOption - добавление опции к команде ffmpeg +# +# DESCRIPTION +# Процедура включает опцию, если в конфигурационном файле имеется +# соответствующая настройка. +# +# USAGE +# enableOption <опция> +# +# ARGUMENTS +# * опция - имя опции из массива настроек config. +# +# SOURCE +# +enableOption () { + if [ ! -z "${config[$1]}" ]; then + CMD+=" $(echo $* | cut -d ' ' -f 2- | sed "s|%%|\"${config[$1]}\"|g")" + fi +} +#***** + +#****f* streamsaver/readXML +# +# NAME +# readXML - чтение файла настроек +# +# DESCRIPTION +# Получение настроек из xml-файла. +# +# USAGE +# readXML +# +# ARGUMENTS +# * xml - файл настроек. +# +# SOURCE +# +readXML() { + #Чтение настроек из файла + for option in ${!config[*]}; { + readOption "$option" "$1" + } +} +#***** + +#****f* streamsaver/makeCMD +# +# 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" -map 0 -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" -map 0 -f segment \ +# -segment_time "$SLICES_TIME" \ +# -segment_format "$FORMAT" \ +# -strftime 1 "$SLICES_DIR/$FILE_NAME" +# +# RESULT +# Команда ffmpeg, которую можно передать на выполнение. +# +# SOURCE +# +makeCMD() { + #Правило именования файлов + FILE_NAME="${config[filename_prefix]}-${config[channel_name]}.${config[filename_suffix]}" + + #Минимальная команда + CMD="${config[cmd]} -reconnect 1 -i ${config[stream]} -f mp2" + # " -f ${config[input_format]}" + + #КОДИРОВАНИЕ + # enableOption output_format -c %% + + #ICECAST + enableOption channel_name \ + -legacy_icecast 1 \ + -content_type audio/mpeg \ + -ice_name %% + + enableOption channel_descr \ + -ice_description %% + + enableOption icecast \ + icecast://source:${config[password]}@${config[icecast]}/${config[mountpoint]} + + # АРХИВ + enableOption archive_log \ + -segment_list %% \ + -segment_list_entry_prefix "${config[archive_dir]}" \ + -segment_list_type csv \ + -segment_list_flags live + + # +СЕГМЕНТИРОВАНИЕ + enableOption archive_dir \ + -segment_atclocktime 1 \ + -acodec "${config[output_format]}" -map 0 \ + -f segment \ + -segment_time "${config[archive_time]}" \ + -segment_format "${config[output_format]}" \ + -strftime 1 "${config[archive_dir]}/$FILE_NAME" + + # АНАЛИЗ + enableOption slices_log \ + -segment_list %% \ + -segment_list_entry_prefix "${config[slices_dir]}" \ + -segment_list_type csv \ + -segment_list_flags live + + # +СЕГМЕНТИРОВАНИЕ + enableOption slices_dir \ + -segment_atclocktime 1 \ + -acodec "${config[output_format]}" -map 0 \ + -f segment \ + -segment_time "${config[slices_time]}" \ + -segment_format "${config[output_format]}" \ + -strftime 1 "${config[slices_dir]}/$FILE_NAME" + + echo "$CMD" +} +#***** + +################################################################################ + +#****v* streamsaver/config +# +# VARIABLE +# config - массив настроек, содержащий значения по-умолчанию. +# Настройки описаны в секции SETTINGS. +# +# USED BY +# enableOption, readOption, readXML, makeCMD +# +# SOURCE +# +typeset -A config + +config=( + [stream]="" + [icecast]="http://localhost:8000/" + [password]="hackme" + [channel_name]="" + [channel_descr]="" + [mountpoint]="" + [cmd]="ffmpeg" + [input_format]="mpegts" + [archive_dir]="" + [archive_time]="3600" + [archive_log]="/var/log/tuc01_archive.log" + [slices_dir]="" + [slices_time]=10 + [slices_log]="/var/log/tuc01_slices.log" + [filename_prefix]="%Y-%m-%d_%H:%M:%S" + [filename_suffix]="mp2" + [output_format]="mp2" + [audio_bitrate]="256k" +) +#***** + +#****v* streamsaver/SETTINGS +# +# VARIABLE +# SETTINGS - файл настроек +# +# DESCRIPTION +# Переменная хранит имя файла настроек, который содержит параметры, +# перечисленные в массиве опций config, в формате XML. При отсутствии +# параметра или пустом значении соответствующие флаги а аргументы не +# добавляются в итоговую команду ffmpeg. Таким образом, например, можно +# включать или отключать ведение журнала сохранения аудиозаписей, просто +# указывая или удаляя параметр archive_log. +# +# Формат файла настроек следующий: +# +# +# +# +# Тестовый_канал +# +# http://localhost:8000/tuc01 +# +# localhost:8000 +# +# hackme +# +# tuc02 +# +# +# ffmpeg +# +# +# mp2 -map 0:0 +# +# +# FILES/archive/ +# +# 3600 +# +# FILES/archive.log +# +# +# FILES/fragments/ +# +# 10 +# +# FILES/fragments.log +# +# +# %Y-%m-%d_%H:%M:%S +# +# mp2 +# +# +# mp2 +# +# 256k +# +# +# SOURCE +# +SETTINGS="$1" +#***** + +#****t* streamsaver/main +# +# NAME +# streamsaver +# +# SOURCE +# + +#Проверка на наличие файла настроек +if [ -z "$SETTINGS" ]; then + echo "USAGE: $(basename $0) " >&2 + exit 1 +elif [ ! -r "$SETTINGS" ]; then + echo "Unable open file $1." >&2 + echo "USAGE: $(basename $0) " >&2 + exit 1 +fi + +#Чтение настроек +readXML "$SETTINGS" + +#Создание директорий хранения файлов, если требуется +mkdir -p ${config[archive_dir]} +mkdir -p ${config[slices_dir]} + +#Создание команды оцифровки сигнала +makeCMD + +#***** +