Сервер потокової трансляції MP3 (OGG)

  у розділі Технічні теми 

icecast2_darkiceХочу поділитись з Вами досвідом встановлення сервера трансляції MP3 (OGG) (на кшталт shoutcast, icecast) з додатковою можливістю збереження трансльованого потоку на диск (архів радіотрансляції).

Таку задачу ми виконували для інтернет-трансляції радіо "Стрий-FM". Таку систему можна використовувати для трансляції аудіопотоку чи в Інтернеті чи в мережевого радіо в локальній мережі.

Загальна інформація

Трансляцією потоку в мережу займатиметься icecast2, джерелом потоку буде darkice, аудіо буде братись з аналогового лінійного входу звукової картки. Спрощена схема така: звукова картка -> darkice -> icecast2 ->мережеві клієнти-слухачі.

Реалізовувалось все на FreeBSD 7.1, проте, в загальному, підійде для будь-якої *nix системи, в тому числі й Linux (в принципі, самі програми доступні і для Windows).

Я буду зосереджуватись лише на найважливішому, вважаючи що базове розуміння встановлення програм та редагування конфігураційних фалів Вами освоєно. :)

Джерело потоку

Якщо Ви плануєте транслювати свою колекцію MP3-музики то можна використовувати icegenerator. Програма просканує локальні диски у пошуках музики та транслюватиме її потоковому демону. Я ж зупинюсь на отриманні звуку з звукової картки.

Налаштування звукової картки

На сервері ми використали просту вбудовану звукову картку. Її встановлення у FreeBSD не було складним.

спочатку треба динамічно підвантажити загальний модуль ядра що відповідає за звук та метадравер що підвантажить усі відомі ядру драйвери звукових карт:

kldload sound
kldload snd_driver

Після цього можна побачити яким модулем побачилась звукова картка та завантажувати лише його, вручну, через /boot/loader.conf, або вкомпілювати просто в ядро (рекомендовано):

# cat /dev/sndstat 
FreeBSD Audio Driver (newpcm: 32bit 2007061600/i386)
Installed devices:
pcm0: <Intel ICH4 (82801DB)> at io 0xdffffa00, 0xdffff900 irq 17 bufsz 16384...

В директорії /dev повинно з'явитись декілька нових пристроїв (це може бути /dev/audo, /dev/mixer, /dev/dsp).

Якщо картка працює нормально, треба вибрати для неї правильний вхід для отримання аудіо (запису). Для цього можна використовувати псевдографічний регулятор рівня каналів aumix (/usr/ports/audio/aumix у FreeBSD) або консольну команду mixer. Зменшіть рівні усіх каналів на нуль, крім rec, та встановіть що записувати з лінійного входу.

У мому випадку, лінійний вхід позначався каналом line.

/usr/sbin/mixer vol 0
/usr/sbin/mixer pcm 0
/usr/sbin/mixer speaker 0
/usr/sbin/mixer line 0
/usr/sbin/mixer mic 0
/usr/sbin/mixer cd 0
/usr/sbin/mixer igain 0
/usr/sbin/mixer ogain 0
/usr/sbin/mixer line1 0
/usr/sbin/mixer phin 0
/usr/sbin/mixer phout 0
/usr/sbin/mixer video 0

/usr/sbin/mixer rec 30
/usr/sbin/mixer =rec line

Можливо прийдеться поекспериментувати з вибором каналу для запису (mixer =rec line <канал>) та рівнями каналів, для якісного звуку (mixer <канал> <рівень>).

Налаштування джерела MP3 потоку - darkice

Аудіо з звукової картки вміє забирати darkice. Після оцифрування, darkice передає потік демону icecast2, який транслює його в мережу.

У FreeBSD darkice без проблем встановлюється з потрів. Після встановлення, створюйте конфігураційний файл:

/usr/local/etc/darkice.cfg

[general]
duration        = 0        # Тривалість декодування. 0 - означає назавжди
bufferSecs      = 5        # розмір буферу, с
reconnect       = yes      # переконекчуватись до сервера, при розриві


[input]
device          = /dev/dsp0.0  # пристрій для отримання аудіосигналу
sampleRate      = 44100        # Частота дискретизації, Гц. 11025, 22050 чи 44100
bitsPerSample   = 16           # розрядність. спробуйте 16
channel         = 2            # к-сть каналів. 1 = моно, 2 = стерео


[icecast2-0]
bitrateMode     = abr       # усереднена якість потоку
format          = mp3       # формат потоку (MP3, OGG, AAC)
bitrate         = 128       # швидкість потоку (кб/с)

server          = localhost #де знаходиться сервер трансляції на який передається потік 
port            = 8000      # порт сервера
password        = HACKME    # пароль для підключення до сервера

mountPoint      = Stryi-FM  # назва віртуальної точки монтування на сервері
name            = Stryi FM  # назва потоку
description     = Radio tvoho mista             # опис потоку
url             = http://fm.stryi.com           # домашня сторінка сервера (просто для інформації)
genre           = Ukrainian, Pop, Rock, Hits    # стиль
public          = no                            # анонсувати в загальнодоступних радіокаталогах?

#localDumpFile   = /radio_archive/a_current.mp3 # якщо плануєте створювати архів

Я прокоментував параметри файлу, тому пояснювати додатково дуже не буду, гадаю все очевидно.

Розділів [icecast2-] може бути декілька ([icecast2-0], [icecast2-1], [icecast2-2], [icecast2-X] і т.д, здається до семи), кожен з своїми налаштуваннями. Крім того є можливість створити розділи [file-0], [file-1], [file-2], [file-X] - для збереження файлів локально, без створення цифрового потоку.

Зверніть лише увагу, на пристрій (device). Насправді, в мене, /dev/dsp0.0 навіть не з'являвся, до першого запуску darkice. А після запуску створився автоматично.

mountPoint - адреса (http://сервер:порт/Адреса), під якою буде видно потік в переліку доступних трансляцій.

Захочете поекспериментувати з якістю чи типом потоку (MP3, OGG, AAC) - пробуйте. Я зупинився на MP3 як на найпоширенішому форматі, хоча OGG і AAC дають кращі результати, навіть за однакових параметрах.

Запуск darkice

В найпростішому випадку darkice можна запускати так:

/usr/local/bin/darkice -c /usr/local/etc/darkice.cfg

У FreeBSD, для автоматичного запуску darkice треба створити такий скрипт:

/etc/rc.d/darkice.sh

#!/bin/sh
# PROVIDE darkice
# REQUIRE icecast2

case "$1" in
start)

    /usr/local/bin/darkice -c /usr/local/etc/darkice.cfg >/dev/null &
    echo $! > /var/run/darkice.pid

    #SYM
    /usr/sbin/mixer vol 0
    /usr/sbin/mixer pcm 0
    /usr/sbin/mixer speaker 0
    /usr/sbin/mixer line 0
    /usr/sbin/mixer mic 0
    /usr/sbin/mixer cd 0
    /usr/sbin/mixer rec 30
    /usr/sbin/mixer igain 0
    /usr/sbin/mixer ogain 0
    /usr/sbin/mixer line1 0
    /usr/sbin/mixer phin 0
    /usr/sbin/mixer phout 0
    /usr/sbin/mixer video 0
    /usr/sbin/mixer =rec line
  ;;

stop)

    kill -TERM `cat /var/run/darkice.pid`
    rm -f /var/run/darkice.pid
  ;;

*)
    echo "Usage: ./darkice.sh [start,stop]" >&2
  ;;

esac

В скрипті, крім запуску самого darkice, створюється файл з номером його процесу (/var/run/darkice.pid), який буде потрібний для створення архіву трансляцій, та регулюються рівні каналів запису, на випадок якщо вони зміняться, після перевантаження. Отут є приклад елегантнішого скрипта (але в ньому не створюється pid-файл).

Тепер, маючи готове джерело аудіопотоку, передаємо його серверу трансляції.

Налаштування сервера трансляції icecast2

Сервіс icecast2 отримує потоки від різних джерел (інші потоки, локальні файли тощо) та дозволяє передавати їх клієнтам (медіа-програвачі тощо).

У FreeBSD від встановлюється без проблем, з портів. Підкорегуйте конфігураційний файл icecast2. Я не буду цитувати його повністю. Зверніть увагу на таке:

/usr/local/etc/icecast.xml

<authentication>\
    <!-- Пароль для джерел які захочуть підключитись -->
    <source-password>HACKME</source-password>

    <!-- дані адміністратора сервера трансляції -->
    <admin-user>admin</admin-user>
    <admin-password>HACKME</admin-password>
</authentication>


 <!-- DNS-ім'я сервера трансляції -->
<hostname>online.fm.stryi.com</hostname>


<listen-socket>
    <!-- Порт який будемо слухати -->
    <port>8000</port>
</listen-socket>


<security>
    <chroot>0</chroot>
    <!-- Від чийого імені виконуємо -->
    <changeowner>
        <user>nobody</user>
        <group>nogroup</group>
    </changeowner>
</security>

Скрипт для автозапуску icecast2, у FreeBSD, встановлюється автоматично, його не треба змінювати.

Тепер, icecast2 запускає веб-сервер на порті 8000 та підключає до себе усі джерела потоків (наприклад вищеналаштований darkice) і підключає їх як доступні трансляції.

Наприклад у мому випадку службова сторінка icecast відкривається як http://online.fm.stryi.com:8000, а до онлайн-трансляції, джерелом якої є darkice можна підключитись за адресою http://online.fm.stryi.com:8000/Stryi-FM.m3u (бо "Stryi-FM" - назва віртуальної точки монтування, вказана у конфігураційному файлі darkice).

Корисні можливості сервера трансляцій icecast2

  • на сторінці http://сервер:8000 можна бачити скільки людей зараз слухає потік та їх максимальну кількість (пік)

  • на сторінці http://сервер:8000/admin/listmounts.xsl можна побачити дані про клієнтів, які зараз під'єднані (List Clients)

  • а Update Metadata дозволяє вказати "поточну пісню" та "виконавця", які відображаються в програвачах слухачів (цей параметр можна передавати HTTP методом POST, для автоматичної зміни такої інформації)

Ось і все. приємного прослуховування вашим онлайн-слухачам. :)

Факультативно. Створення архіву трансляції.

Припустимо що Вам треба ще й зберігати онлайн-трансляцію у локальний файл. Для радіостанцій (не інтерне, а навіть звичайних) взагалі є така вимога. Та й деколи корисно мати такий архів, щоб при потреб прослухати що транслювалось.

Для цього, найспростіше, скористатись можливістю самого darkice. Додайте в конфігураційний файл таке:

/usr/local/etc/darkice.conf

localDumpFile   = /radio_archive/a_current.mp3

Тепер, разом з кодуванням аудіопотоку darkice буде автоматично створювати файл /radio_archive/a_current.mp3 (файл буде в тому форматі, в якому задано формування потоку).

Проте цей файл буде просто постійно зростати в розмірі. Щоб використовувати його з користю треба якось, час від часу, "забирати" його та зберігати з іншою назвою.

Насправді все не так просто. Документація darkice предбачає можливість керування цим файлом, проте якось не до кінця описується принцип роботи. Я знайшов декілька посилань на неіснуючу сторінку Wiki проекту darkice де описувалось як правильно зберігати файли. але саму сторінку знайшов лише у веб-архіві 2007-го року. :)

Отже суть, виявляється, така: darkice створює файл у вказаній вами директорії. Для того щоб файл перейменувався та почав писатись новий треба надіслати процесу сигнал SIGUSR1 (signal 10).

Але (!) назву і шлях до файлу в який треба перейменувати поточний файл, darkice шукає у файлі /tmp/darkice.потік.PID, де:

  • потік - це назва розділу ([icecast2-0], [icecast2-1], [icecast2-2], [icecast2-X])

  • PID - номер запущеного процесу darkice

Приклад:

Darkice запустився процесом під номером 25600 (можна взнати командою "ps | grep darkice"). Ви хочете зберегти файл потоку icecast2-0 у файл з назвою 18.05.09.mp3.

Тоді створіть файл /tmp/darkice.icecast2-0.25600 з таким змістом: "18.05.09.mp3", та надішліть процесу darkice сигнал SIGUSR1:

kill -USR1 25600

Для Linux напевне треба писати "kill -SIGUSR1 25600" чи "kill -s 10 25600".

Тоді, файл вказаний у опції "localDumpFile" перейменується у "18.05.09.mp3" та почне писатись "з нуля".

Скрипт для автоматичної щогодинної архівації трансльованого потоку

Щоб це все трохи автоматизувати я створив простий скрипт, що створює файли з датою та годиною у назві. Якщо його запускати по крону щогодини то отримуємо архів файлів з назвами

  • 2009.05.18_15-16.mp3

  • 2009.05.18_16-17.mp3

  • 2009.05.18_17-18.mp3

  • ...

radio_archive.sh

#!/bin/sh
#SYM
#Архів радіотрансляцій
#0       *       *       *       *       root    /usr/local/bin/radio_archive.sh

PID=`/bin/cat /var/run/darkice.pid`
start_date=`/bin/date -v-1H +%Y.%m.%d_%H`
cur_time=`/bin/date +%H`

#Затираємо "хвости"
/bin/rm /tmp/darkice.icecast2-0.*

#Створюємо новий файл
echo "/radio_archive/${start_date}-${cur_time}.mp3" > /tmp/darkice.icecast2-0.$PID

#Надсилаємо сигнал демону
kill -USR1 $PID

exit 0

Запускайте його сервісом cron, щогодини. Година в якій запуститься скрипт є кінцевою годиною запису. Зверніть увагу на правильний синтаксис "kill -USR1" для Вашої системи (приклади для Linux описані вище). Майте на увазі, що для створення файлу /var/run/darkice.pid треба використовувати скрипт запуску, який його створює (описано вище).

Сподіваюсь що стаття стане комусь в пригоді. Якщо маєте конкретні питання - буду радий відповісти.


Коментарі