Мы — долго запрягаем, быстро ездим, и сильно тормозим.
www.lissyara.su —> статьи —> FreeBSD —> программы —> Icecast2 + Darkice

Подъем интернет-радиостанции с возможностью ретрансляции внешний станций

Автор: unkn0wn.


Однажды вечером, сидя в рздумьях, что ты такое натворить, в моей голове созрел план поднять Инет-радиостанцию. Сказано - сделано. Инет был перерыскан на тему потоковых серверов и сорс-клиентов к ним, и выбор пал на связку Icecast2+Darkice. Shoutcast отвалился сразу по причине примитивного конфига, и двухдневного марафона на тему "Как же тебе всунуть этот аудиопоток!", ибо к нему никто из сорсов не хотел подключаться, а Darkice был выбран по причине того, что меня прельстили удобный конфиг, возможность записи радиопередач в отдельные файлы, и то, что связка с Icecast заработала сразу без какого бы то ни было точения напильником.

Первым делом, была выбрана схема с двумя серверами Icecast2. Дело в том, что Darkice выпадает по signal 6 после того, как более 6 минут не может подключиться в серверу вещания, плюс во время установления соединения в файл эфира он пишет полную чушь, потому было принято решение вещать по схеме (Darkice)->локальный Icecast -> релей с внешнего Icecast, впрочем, эту схему легко поправить.

Часть 1. Настройка машины в локальной сети
=================================================================

Первым делом пошел в /usr/ports/audio/icecast2, сделал make install clean, и (о чудо!) через несколько минут сборки icecast2 собрался и установлся. Дальше путь мой лежал в /usr/local/etc/, в котором я создал файл icecast.xml следующего содержимого:
<icecast>
    <limits>
        <clients>100</clients>
        <sources>2</sources>
        <threadpool>5</threadpool>
        <queue-size>524288</queue-size>
        <client-timeout>30</client-timeout>
        <header-timeout>15</header-timeout>
        <source-timeout>10</source-timeout>
        <burst-on-connect>1</burst-on-connect>
        <burst-size>65535</burst-size>
    </limits>

    <authentication>
        <source-password>123456</source-password>
        <relay-password>hackme</relay-password>
        <admin-user>admin</admin-user>
        <admin-password>hackme</admin-password>
    </authentication>

    <hostname>localhost</hostname>

    <listen-socket>
        <port>8000</port>
        <bind-address>192.168.0.253</bind-address>
    </listen-socket>

    <mount>
    <mount-name>/MyRadio</mount-name>
    <max-listeners>2</max-listeners>
    <burst-size>65536</burst-size>
    </mount>

    <fileserve>1</fileserve>

    <paths>
        <basedir>/var/icecast</basedir>
        <logdir>/log</logdir>
        <webroot>/web</webroot>
        <adminroot>/admin</adminroot>
        <pidfile>/run/icecast.pid</pidfile>
        <alias source="/" dest="/status.xsl"/>
    </paths>

    <logging>
        <accesslog>access.log</accesslog>
        <errorlog>error.log</errorlog>
          <loglevel>2</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
          <logsize>10000</logsize> <!-- Max size of a logfile -->
        <logarchive>1</logarchive>
    </logging>

    <security>
        <chroot>1</chroot>
        <changeowner>
            <user>icecast</user>
            <group>icecast</group>
        </changeowner>
    </security>
</icecast>

После этого были созданы пользователь icecast, группа icecast, папки /var/icecast/log, /var/icecast/web, /var/icecast/admin и /var/icecast/run, в них было скопировано содержимое папки /usr/local/share/icecast, и сделано
chown -R icecast:icecast /var/icecast

.

Итак, сервер у нас есть, остается подать ему поток. В портах лежит занимательная программа - Darkice. Идем в /usr/ports/audio/darkice, вбиваем в консоли
make install clean

, и вот Darkice уже стоит. Немного пошаманил с конфигом /usr/local/etc/darkice.cfg, и вот что получилось:

# this section describes general aspects of the live streaming session
[general]
duration        = 0        # длительность оцифровки в секундах, 0 - бесконечно
bufferSecs      = 5        # длительность внутренней буферизации, в секундах
reconnect       = yes      # переподключаться в случае дисконнекта с сервером
realtime        = no       # оцифровка в режиме реального времени или нет

# this section describes the audio input that will be streamed
[input]
device          = /dev/dsp0   # устройство OSS DSP звуковой карты
sampleRate      = 44100       # частота дискретизации в Герцах: 11025, 22050 или 44100
bitsPerSample   = 16          # бит на семпл, 8 или 16
channel         = 2           # каналов: 1 = моно, 2 = стерео

[icecast2-0]
bitrateMode     = cbr         # тип кодирования, допустимы vbr/abr/cbr
format          = mp3         # формат потока: mp3/ogg
bitrate         = 128         # битрейд потока
server          = 192.168.0.253     # имя хоста, на котором поднят Icecast2 (допустим IP-адрес)
port            = 8000        # порт, на котором слушает сервер IceCast2, обычно 8000
password        = 123456      # пароль для учетной записи source на сервере IceCast2
mountPoint      = MyRadio     # точка монтирования на сервере IceCast2
name            = MyRadio     # название потока
description     = MyRadio     # описание потока
url             = http://none # произвольный адрес
genre           = misc        # жанр
public          = no          # публиковать на dir.xith.org или нет?

Конфиг простой до безобразия: надо указать звуковое устройство (/dev/dsp0), адрес и порт сервера, логин/пароль к нему и точку монтирования. Пароль берем из секции <authentication>, поля <source-password>
* Если поставите realtime = yes - гарантированно получите 100%-ую загрузку процессора, с чем это связано - так и не выяснил, связывался с автором - он ничего толком не объяснил


Для запуска darkice был накатан сей скрипт, названный darkice.sh:
#!/bin/sh

# PROVIDE darkice
# REQUIRE amixer icecast2

case "$1" in
start)

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

faststart)

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

stop)

    kill -TERM `cat /var/run/darkice.pid`
    rm -f /var/run/darkice.pid
  ;;
    
*)
    echo "Usage: ./darkice.sh start" >&2
  ;;

esac

и положен в /usr/local/etc/rc.d

При первом запуске встала проблема, заключающаяся в том, что по умолчанию звук брался не с линейного входа, а с микрофонного, да и уровень по умолчанию зашкаливал, посему был написан сей скрипт, названный amixer.sh:
#!/bin/sh

# PROVIDE amixer
# BEFORE darkice

case "$1" in
start)

    mixer -f /dev/dsp0 rec 55 line 55 mic 0 >/dev/null
    mixer -f /dev/dsp0 -s =rec line >/dev/null

;;
faststart)

    mixer -f /dev/dsp0 rec 55 line 55 mic 0 >/dev/null
    mixer -f /dev/dsp0 -s =rec line >/dev/null

;;

*)
    echo "Usage: amixer start" >&2
;;
esac

и положен в /usr/local/etc/rc.d
* Если вы хотите брать звук с другого устройства и(ли) изменить уровень сигнала, поправьте строчку mixer -f /dev/dsp0 rec 55 line 55 mic 0 >/dev/null

Далее путь лежал в /etc/rc.conf, в которые былы вбиты следующие строки
icecast_enable="YES"
icecast_flags="-c /usr/local/etc/icecast.xml"
darkice_enable="YES"
amixer_enable="YES"

Пускаем сперва Icecast, потом amixer, потом Darkice, топаем на http://192.168.0.253:8000, и наслаждаемся поднятой радиостанции. Если вы хотите вещать непосредственно с этой машины, то можно только поправить <max-listeners> и точку монтирования, и раздавать всем урлы вида http://192.168.0.253:8000, дабы люди ходили к вам за pls'ками, но в моем случае эта машина была в локальной сети, а поток надо было пробросить на внешний сервер.

Часть 2. Настройка машины во внешней сети
=================================================================

Недолго думая, на внешнем сервере поднимаю еще один Icecast2-сервер, пишу конфиг /usr/local/etc/icecast.xml:

<icecast>
    <limits>
        <clients>100</clients>
        <sources>3</sources>
        <threadpool>5</threadpool>
        <queue-size>524288</queue-size>
        <client-timeout>30</client-timeout>
        <header-timeout>15</header-timeout>
        <source-timeout>10</source-timeout>
         <burst-on-connect>1</burst-on-connect>
    </limits>

    <authentication>
        <source-password>hackme</source-password>
        <relay-password>hackme</relay-password>
        <admin-user>admin</admin-user>
        <admin-password>hackme</admin-password>
    </authentication>

    <hostname>radio.host.ru</hostname>

    <listen-socket>
        <port>8000</port>
        <bind-address>83.176.111.8</bind-address>
    </listen-socket>
    
    <listen-socket>
        <port>8001</port>
    <bind-address>83.176.111.8</bind-address>
    </listen-socket>


    <relay>
        <server>192.168.0.253</server>
        <port>8000</port>
        <mount>/MyRadio</mount>
        <local-mount>/MyRadio</local-mount>
        <on-demand>0</on-demand>

        <relay-shoutcast-metadata>0</relay-shoutcast-metadata>
    </relay>

    <mount>
    <mount-name>/MyRadio</mount-name>
    <max-listeners>100</max-listeners>
        <burst-size>65536</burst-size>
    </mount>
    

    <fileserve>1</fileserve>

    <paths>
        <basedir>/var/icecast</basedir>
        <logdir>/logs</logdir>
        <webroot>/web</webroot>
        <adminroot>/admin</adminroot>
        <pidfile>/run/icecast.pid</pidfile>
        <alias source="/" dest="/status.xsl"/>
    </paths>

    <logging>
        <accesslog>access.log</accesslog>
        <errorlog>error.log</errorlog>
          <loglevel>1</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
          <logsize>10000</logsize> <!-- Max size of a logfile -->
        <logarchive>1</logarchive>
    </logging>

    <security>
        <chroot>1</chroot>
        <changeowner>
            <user>icecast</user>
            <group>icecast</group>
        </changeowner>
    </security>

</icecast>

, и проведены аналогичные манипуляции с юзером/группой icecast и /var/icecast, как и выше.

ВАЖНО: Не забудьте сменить с конфигах Icecast'a и, соответственно, в Darkice'а пароли 123456 и hackme на что-то более серьезное!

Сразу оговорюсь, что эта машина имеет два интерфейса: один смотрит в локальную сеть, чтобы забирать поток с 192.168.0.253, другой во внешнюю.

Отличительная особенность этого конфига в том, что в нем появились секции <relay>...</relay>, назначение которых - указать серверу, откуда брать потом и в какую точку его монтировать, в данном случае указывает брать поток с 192.168.0.253:8000/MyRadio и монтировать его в локальную точку /MyRadio.

Пишем в /etc/rc.conf:
icecast_enable="YES"
icecast_flags="-c /usr/local/etc/icecast.xml"

и делаем
/usr/local/etc/rc.d/icecast2 start

После этого внешний Icecast-сервер берет поток с внутреннего сервера, и его ретранслирует. Людям раздаются урлы вида http://radio.host.ru:8000 либо http://83.176.111.8:8000/, чтобы они заходили на главную страницу сервера вещания и забирали оттуда .m3u-файлы вручную, либо самим зайти по данному адресу и выдернуть со страницы урлы на .m3u.

Можно заметить, что внешний сервер слушает на двух портах, в то время как внутренний только на одном. Проблема заключается в том, что Shoutcast открывает два порта, один какой прописан в конфиге, второй на единицу больше, и дабы не сбивать с толку плееры, заточенные под эту модель, была сделна эта поправка в конфигах.

Если есть желание ретранслировать радио, в секции <relay> в поле <server> надо указать сервер, откуда берете поток, а в поле <port> - соответственно порт сервера.

Касательно ретрансляции с различных серверов: если вы ретранслируете с сервера Icecast, то в поле <mount> надо указывать точку на удаленном сервере, если же с сервера Shoutcast - то просто /. Разница заключается в том, что Icecast - mount-based сервер, в то время как Shoutcast - port-based, то есть один экземпляр icecast может поддерживать практически неограниченое количество станций на одном порту, в то время как shoutcast придерживается идеологии "один порт - одна станция".



размещено: 2007-11-21,
последнее обновление: 2007-11-26,
автор: unkn0wn


Banec, 2007-12-22 в 17:01:40

 Если вы хотите вещать непосредственно с этой машины, то можно только поправить <max-listeners> и точку монтирования, и раздавать всем урлы вида http://192.168.0.253:8000, дабы люди ходили к вам за pls'ками, но в моем случае эта машина была в локальной сети, а поток надо было пробросить на внешний сервер.

Что и где подправить?

unkn0wn, 2007-12-30 в 21:20:48

icecast.xml. А вообще обсуждение идет в этой ветке: http://forum.lissyara.su/viewtopic.php?f=14&t=5943&start=0&st=0&sk=t&sd=a

InventoR, 2008-04-08 в 13:53:36

ссылка на обсуждение мертвая

Bob_St, 2008-10-22 в 16:19:27

<max-listeners>2</max-listeners>
Чтоб смогло подключиться к потоковому серверу больше 2 клиентов (например 40)- необходимо заменить значение на 40

killerxxl, 2008-12-26 в 16:42:42

auu pomogite pojalusta neponel gde eti faili /usr/ports/audio/icecast2  /usr/local/etc/ vso skachal vso u menia est tolko eto neponal gde eto iskatt pomogite pojalustaaa moi mail:artuom93.93@mail.ru

Sha Rikoff, 2009-02-08 в 23:18:58

"Restarting icecast2: Starting icecast2
Detaching from the console
WARNING: Cannot change server root unless running as root.
icecast2.
root@sha-home:/home/sha# FATAL: could not open error logging (/log/error.log): No such file or directory
FATAL: could not open access logging (/log/access.log): No such file or directory
FATAL: Could not start logging"  - притом все теки и файлы в них физически присутствуют. Почему такое странное сообщение?  

unkn0wn, 2009-02-09 в 14:04:37

Скорее всего, не задано <user>/<group> в секции <security>, либо юзвери/группы, указанные там, не созданы в системе. Далее, в секции <paths> задается директория <basedir>, относительно нее и формируются остальные пути, в данном случае /var/icecast/logs, /var/icecast/web.
То есть, либо заданы неверные юзер/группа, либо папки лежат не там, где им надо быть.

poison, 2009-04-27 в 15:17:23

Спасибо за статью, пригодилась недавно, захотел радио слушать на работе, решил сперва поставить дома DVB карту SS2 но ради одного радио стало жалко,
поставил старый спутниковый ресивер XSAT CDTV 300 и с него стал брать, на линейный вход звуковой карты,
В ядро:
#Sound devices
device          sound           #
device          snd_es137x      #
далее подправил скрипт для darkice

rj45# cat /usr/local/etc/rc.d/darkice.sh
#!/bin/sh

# PROVIDE darkice
# REQUIRE amixer icecast2
DESC="Darkice"
daemon="/usr/sbin/daemon"
darkice="/usr/local/bin/darkice"
conf="/usr/local/etc/darkice.cfg"
pid="/var/run/darkice.pid"

case "$1" in
   start)
       if [ -f ${pid} ]
       then
           echo -n "${DESC} already runnig"
           echo "!"
       else
           echo -n "${DESC} starting"
           ${daemon} -p ${pid} ${darkice} -c ${conf} >/dev/null 2>&1
           echo "."
       fi
   ;;

   stop)
       if [ -f ${pid} ]
       then
           echo -n "${DESC} stopping"
           kill -TERM `cat ${pid}` 2>&1
           rm -f ${pid}
           echo "."
       else
           echo -n "${DESC} is not running"
           echo "."
       fi
   ;;

   *)
       echo "Usage: `basename $0` {start|stop}" >&2
   ;;

esac

для миксера скрипт отсюда, без него кстати не заводилось, darkice стартовал но звука не было, пока не ввел mixer -f /dev/dsp0 -s =rec line >/dev/null 2>&1

все остальное как у автора.
Thanks!

poison, 2009-04-27 в 21:07:16

Единственное замечание к автору, ошибки по тексту в плане русского языка.

Trider, 2009-06-13 в 23:59:02

Сделал все по статье, не парсит музыку... В чем может быть проблема?

unkn0wn, 2009-06-25 в 16:26:26

В смысле не парсит? Не берет аудиопоток со звуковой карты, не отдает поток на айс, айс не отдает поток? Конкретнее.

alex, 2009-09-04 в 15:01:39

Лично у меня скрипт amixer необходимо запускать после darkice (сбивает настройки микшера, зараза). А т.к. в статье ошибка в скриптах (# PROVIDE darkice вместо # PROVIDE: darkice и т.д.) мучился долго. Просьба добавить двоеточия в нужные места.

ЗЫ Вот у товарища poison та же беда

poison, 2009-09-04 в 15:11:04

2 alex
я давно уже переделал скрипт, у мя при запуске скприпта darkice.sh задаются параметры микшера, чтоб не было что один раньше запустился другой позже.

cat /usr/local/etc/rc.d/darkice.sh
#!/bin/sh
DESC="Darkice"
daemon="/usr/sbin/daemon"
darkice="/usr/local/bin/darkice"
conf="/usr/local/etc/darkice.cfg"
pid="/var/run/darkice.pid"

case "$1" in
   start)
       if [ -f ${pid} ]
       then
           echo -n "${DESC} already runnig"
           echo "!"
       else
           echo -n "${DESC} starting"
           mixer -f /dev/dsp0 rec 55 line 55 mic 0 > /dev/null 2>&1
           mixer -f /dev/dsp0 -s =rec line > /dev/null 2>&1
           ${daemon} -p ${pid} ${darkice} -c ${conf} >/dev/null 2>&1
           echo "."
       fi
   ;;

   stop)
       if [ -f ${pid} ]
       then
           echo -n "${DESC} stopping"
           kill -TERM `cat ${pid}` 2>&1
           rm -f ${pid}
           echo "."
       else
           echo -n "${DESC} is not running"
           echo "."
       fi
   ;;

   *)
       echo "Usage: `basename $0` {start|stop}" >&2
   ;;

esac



 

  Этот информационный блок появился по той простой причине, что многие считают нормальным, брать чужую информацию не уведомляя автора (что не так страшно), и не оставляя линк на оригинал и автора — что более существенно. Я не против распространения информации — только за. Только условие простое — извольте подписывать автора, и оставлять линк на оригинальную страницу в виде прямой, активной, нескриптовой, незакрытой от индексирования, и не запрещенной для следования роботов ссылки.
  Если соизволите поставить автора в известность — то вообще почёт вам и уважение.

© lissyara 2006-10-24 08:47 MSK

Время генерации страницы 0.2084 секунд
Из них PHP: 57%; SQL: 43%; Число SQL-запросов: 77 шт.
Исходный размер: 47474; Сжатая: 11173