使用 Icecast 和 Liquidsoap 创建互联网广播电台
是否曾想为互联网受众直播预先录制的音乐或现场活动,例如讲座或音乐会?借助 Icecast 和 Liquidsoap,您可以使用自由软件和开放标准设置功能齐全、灵活的互联网广播电台。
Icecast 是“一个流媒体(音频/视频)服务器,目前支持 Ogg(Vorbis 和 Theora)、Opus、WebM 和 MP3 流。它可用于创建互联网广播电台或私下运行的自动点唱机,以及介于两者之间的许多事物。它非常通用,可以相对容易地添加新格式,并支持用于通信和交互的开放标准。”
Liquidsoap 是“一种强大而灵活的语言,用于描述您的流。它提供了丰富的运算符集合,您可以随意组合这些运算符,为您提供比创建或转换流所需的更多功能。但是 Liquidsoap 仍然非常轻巧且易于使用,符合 UNIX 简单而强大的组件协同工作的传统。”
当结合使用时,Icecast 和 Liquidsoap 可以创建一个灵活、功能丰富的互联网广播电台。在本文中,我将描述如何配置 Icecast 以托管互联网广播电台。然后,我将解释如何安装和配置 Liquidsoap 以连接到 Icecast,添加具有智能交叉淡入淡出的随机(或顺序)音乐播放、预先录制的随机插入的公告和叮当声、歌曲请求系统以及对直播流的支持,并具有自动录制和在直播和自动节目之间的无缝切换。我还将展示如何配置服务器以 MP3、Ogg 和 Opus 格式提供您的流,以实现最大的播放器兼容性。
Icecast、Vorbis 和相关项目由非营利组织 Xiph.Org 维护,该组织开发开放多媒体标准和软件。为了确保您运行的是最新版本的 Icecast,并具有所有(或大多数)功能,您应该从官方 Xiph.Org 存储库安装。访问官方存储库列表 此处,并按照该页面上的说明为您的发行版添加 Icecast 存储库。然后,使用您的系统软件包管理器进行安装。在基于 Debian 的系统(如 Ubuntu)上,可能会要求您在软件包安装期间“配置 Icecast”;选择“否”,因为如果您按照本文进行操作,您将手动配置服务器。
使用您喜欢的文本编辑器打开 Icecast 配置文件。在基于 Debian 的系统上,该文件位于 /etc/icecast2/icecast.xml。其他系统上的位置可能不同;请查看您的软件包文档以获取正确的路径。配置文件为 XML 格式,分为几个部分。首先,分别在 location 和 admin 字段中输入您服务器的位置和电子邮件地址——例如
<location>The Heart of Gold</location>
<admin>zaphodb42@mail.example.com</admin>
由于您将在 Liquidsoap 中设置的每种格式都是一个单独的 Icecast“源”,因此您将很快耗尽默认的两个源限制。因此,将其更改为十个
<sources>10</sources>
除非您预计听众会从缓慢或低带宽环境中连接,否则禁用 Icecast 的 burst-on-connect 功能将显着降低延迟
<burst-on-connect>0</burst-on-connect>
<burst-size>0</burst-size>
默认密码“hackme”会邀请安全漏洞。将它们更改为其他内容。此外,更改默认的管理员用户名可能也是一个好主意。以下密码仅为示例;请在此处以及在文章后面提及它们时,为您的配置更改它们
<source-password>dontpanic</source-password>
<relay-password>dontpanic42</relay-password>
<admin-user>zaphod</admin-user>
<admin-password>2Headsarebetterthanone!</admin-password>
在 hostname 字段中输入您系统的完全限定域名
<hostname>example.com</hostname>
保存并关闭文件。如果您以 root 用户身份编辑了文件,则需要重置其权限。在基于 Debian 的系统上,Icecast 在用户 icecast2 和组 icecast 下运行。要在基于 Debian 的系统上修复权限,请运行
chown icecast2:icecast /etc/icecast2/icecast.xml
在基于 Debian 的系统上,默认情况下禁用 Icecast 的系统服务。打开文件 /etc/default/icecast2,并将 enabled 设置为 true。然后保存并关闭文件。
大多数现代 Linux 系统使用 systemd 进行服务管理。要在启动时启用 Icecast 并为此会话启动它,请以 root 用户身份运行以下命令(使用 sudo 或类似命令)
systemctl enable icecast2
systemctl start icecast2
各种系统上的服务名称有所不同;如果这些命令不起作用,请查看您的系统文档以获取正确的服务名称。
许多发行版在其存储库中提供了损坏和过时的 Liquidsoap 版本。出于这个原因(以及提高自定义安装的能力),Liquidsoap 开发人员建议使用 OCaml 软件包管理器 (opam) 安装它。使用您的发行版的软件包管理器安装 opam。如果您到目前为止所做的一切都是以 root 用户身份登录的,那么您现在需要创建一个非 root 用户来安装 Liquidsoap。您还需要安装 sudo 并授予此新用户使用它的权限。在基于 Debian 的系统上,adduser
和 gpasswd
实用程序允许您分别创建用户并将他们添加到组中。在基于 Debian 的系统上,以 root 用户身份运行以下命令以添加新用户并授予其 sudo 访问权限(对于其他系统,请参阅文档)。让 username
代表新用户的用户名
adduser username
gpasswd -a username sudo
以您的非 root 用户身份执行,通过运行以下命令初始化 OCaml 软件包管理器
opam init
当被询问是否修改您的配置文件时,回答“yes”;这将把 Liquidsoap 放在您的路径中,并允许您在键入其名称时执行它。要应用 opam 更改,请运行
eval `opam config env`
接下来,安装 Liquidsoap 的系统依赖项
opam install depext
opam depext taglib mad lame vorbis cry ssl samplerate
↪magic opus liquidsoap
现在,通过将 depext
替换为 install
来安装 liquidsoap
opam install taglib mad lame vorbis cry ssl samplerate
↪magic opus liquidsoap
为了为电台配置设置起点并将 Liquidsoap 启用为服务,开发人员创建了 liquidsoap-daemon,这是一组用于将 Liquidsoap 用作系统服务的脚本。Liquidsoap-daemon 默认使用 systemd 进行服务管理;因此,它与大多数现代 Linux 发行版兼容。要设置它,请使用您的系统软件包管理器安装 Git,然后以您的非 root 用户身份运行以下命令
git clone https://github.com/savonet/liquidsoap-daemon
cd liquidsoap-daemon
./daemonize-liquidsoap.sh
系统可能会提示您输入用户密码以验证 sudo。安装 dæmon 后,您现在将在非 root 用户的主目录中创建一个目录结构,用于存储音乐、叮当声和直播流的存档。运行以下命令
mkdir -p ~/music/music1 ~/music/jingles ~/archives
现在,打开 liquidsoap-daemon 目录中的文件 main.liq。此时,该文件仅包含
output.dummy(blank())
此行不会向任何地方发送音频,这非常无趣,因此删除该行并添加以下基本配置(以 # 开头的行是注释,因此 Liquidsoap 会忽略它们)。此基本配置设置了一个音乐播放列表,其中歌曲以随机顺序播放,大约每七首歌曲插入一次叮当声,智能交叉淡入淡出,歌曲请求和自动录制的直播流。music.mp3、music.ogg 和 music.opus 分别以 MP3、Ogg Vorbis 和 Ogg Opus 格式流式传输存储的音乐和叮当声;stream.mp3、stream.ogg 和 stream.opus 在直播流可用时播放直播流,并在直播流中断时回退到音乐
#Settings
set("server.telnet", true)
set("server.telnet.port", 1234)
set("harbor.bind_addr","0.0.0.0")
# Music playlists
music1 = playlist("~/music/music1")
# Some jingles
jingles = playlist("~/music/jingles")
# If something goes wrong, we'll play this
security = single("~/music/default.ogg")
# Start building the feed with music
radio = random([music1])
# Add the security, requests and smart crossfade
radio = fallback(track_sensitive = false,
↪[smart_crossfade(fallback([request.queue(id="request"),
↪radio])),security])
# Now add some jingles
radio = random(weights = [1, 7],[jingles, radio]) # This plays
# a jingle once every approximately seven songs, change 7 to
# another number to change this
# Add a skip command for the music stream
server.register(
usage="skip",
description="Skip the current song.",
"skip",
fun(_) -> begin source.skip(radio) "Done!" end
#Add support for live streams.
live =
audio_to_stereo(input.harbor("live",port=8080,password=
↪"dontpanic1764",buffer=1.0)) #dontpanic1764 is the
# password used to connect a live stream; it can (and should) be
# different from the source-password in icecast.xml.
full = fallback(track_sensitive=false,
[live,radio])
# Dump archives
file_name = '~/archives/%Y-%m-%d-%H:%M:%S$(if $(title),
↪"-$(title)","").ogg'
output.file(%vorbis,file_name,live,fallible=true)
# Stream it out
output.icecast(%mp3.vbr,
host = "localhost", port = 8000,
password = "dontpanic", mount = "music.mp3",
name="myStation Music Service", description="This is the myStation
↪music stream. Add some information about your station's automated
↪programming.",
radio)
output.icecast(%vorbis,
host = "localhost", port = 8000,
password = "dontpanic", mount = "music.ogg",
name="myStation Music Service", description="This is the myStation
↪music stream. Add some information about your station's
↪automated programming.",
radio)
output.icecast(%opus(vbr="unconstrained",bitrate=60),
host = "localhost", port = 8000,
password = "dontpanic", mount = "music.opus",
name="myStation Music Service", description="This is the myStation
↪music stream. Add some information about your station's
↪automated programming.",
radio)
output.icecast(%mp3.vbr,
host = "localhost", port = 8000,
password = "dontpanic", mount = "stream.mp3",
name="myStation Main Stream", description="The myStation main stream.",
full)
output.icecast(%vorbis,
host="localhost",port=8000,password="dontpanic",
mount="stream.ogg",
name="myStation Main Stream", description="The myStation main stream.",
full)
output.icecast(%opus(vbr="unconstrained",bitrate=60),
↪description="The myStation main stream.",
host="localhost",port=8000,password="dontpanic",
mount="stream.opus",
full)
多个音乐播放列表
您可能希望设置多个音乐播放列表,可能具有不同类型的音乐,并更改每个播放列表中的歌曲播放频率。为此,在 music 下为每个播放列表创建目录,命名为 music2、music3 等。然后只需复制 main.liq 的音乐播放列表部分中的 music1
行,并相应地更改对 music1
的引用。
要每 n 首歌曲从新播放列表中随机插入歌曲,请在 radio = random([music1])
下方添加一行,其中 n
表示在从新播放列表中插入歌曲之前要播放的歌曲的大概数量
radio = random(weights = [1, n],[music2, radio])
这是一个包含三个音乐播放列表的示例
# Music playlists
music1 = playlist("~/music/music1")
music2 = playlist("~/music/music2")
music3 = playlist("~/music/music3")
...
radio = random([music1])
radio = random(weights = [1, 6],[music2, radio])
radio = random(weights = [1,12],[music3, radio])
基于文件的播放列表
在基本配置中,Liquidsoap 将递归搜索目录 ~/music/music1 以查找要播放的歌曲。但是,您也可以为 Liquidsoap 提供一个换行符分隔的歌曲路径文本文件,该文件可以位于您的系统本地或 Web 上。为此,只需将目录路径更改为文本文件的路径,如下所示
music1 = playlist("~/music/music1.pls")
顺序播放
默认情况下,Liquidsoap 以随机顺序播放曲目。如果您想按顺序播放曲目,请在您的播放列表定义中添加 mode="sequential"
,如下所示
music1 = playlist("~/music/music1",mode="sequential")
与其使用 random
(例如,在添加其他播放列表或叮当声时),不如使用 rotate
radio = rotate(weights = [1, 7],[jingles, radio])
顺序播放最好与基于文件的播放列表结合使用,因为它们都使您可以完全控制 Liquidsoap 播放曲目的顺序。
压缩和标准化如果您想为您的自动节目添加更“类似广播”的声音,Liquidsoap 支持自动压缩和标准化。要压缩和标准化播放列表或 input.harbor 直播流的曲目,请将其包装在 nrj()
运算符中,如下所示
music1 = nrj(playlist("~/music/music1"))
在自动节目上讲话
您可以添加一个挂载点,允许您在自动节目上讲话,这会在您连接时降低其音量。在您的配置中,在 #Add support for live streams
上方添加以下内容。在麦克风连接时,自动节目音量将更改为正常音量的 15%;更改 p=0.15
以进行调整
# Talk over stream using microphone mount.
mic=input.harbor("mic",port=8080,password="dontpanic1764",buffer=1.0)
radio = smooth_add(delay=0.8, p=0.15, normal=radio, special=mic)
完成
根据需要编辑配置,然后保存并关闭文件。录制一个文件到 ~/music/default.ogg;当 Liquidsoap 找不到其他曲目播放时,将播放此文件。该文件应告知听众流已中断,并向他们提供联系您的信息以通知您问题。用音乐填充播放列表,然后使用以下命令启动 Liquidsoap
sudo systemctl start liquidsoap
在启动时启用它
sudo systemctl enable liquidsoap
Liquidsoap 启动后,在 Web 浏览器中访问 http://example.com:8000(其中 example.com 是您服务器的完全限定域名)。如果您的系统配置正确,则会显示 music.mp3、music.ogg 和 music.opus,并播放自动节目。此外,除非连接了直播流,否则 stream.mp3、stream.ogg 和 stream.opus 将播放自动节目。
如果 Icecast 出现但未列出任何挂载点,请检查 liquidsoap-daemon/log/run.log 中的 Liquidsoap 日志以查找错误。如果 Icecast 未加载,请使用 systemctl restart icecast2
重新启动它。
要通过您的服务器广播直播流,您将需要一个兼容的源客户端。对于 Windows,我推荐 Altacast。对于 Mac 用户,我建议使用 Ladiocast,可在 Mac App Store 中找到。对于 Linux,请通过您的系统软件包管理器安装 DarkIce。在 iOS 上,我推荐 iCast。在 Android 上,我建议使用 Cool Mic。在所有情况下,请使用以下配置
-
主机:您服务器的完全限定域名。
-
端口:8080
-
挂载(挂载点):live(或 /live)用于直播流。如果您启用了在自动节目上讲话的功能,请将
live
替换为mic
以在音乐上讲话。 -
用户名:source(某些客户端不会提示输入用户名,在这种情况下,source 是隐含的默认值)。
-
密码:dontpanic1764(或您在 input.harbor 配置中指定的密码)。
您可以以 Ogg Vorbis 或 MP3 格式流式传输。Ogg Opus 可能有效,也可能无效,具体取决于您的源客户端。
Liquidsoap 提供通过 TCP(通过 telnet 或类似协议)进行控制。本文介绍的基本配置启用了歌曲请求系统和按需跳过曲目的功能。默认情况下,此接口仅对本地系统上的用户可用。telnet 协议不支持身份验证。如果您想让您的用户可以使用歌曲请求功能,您需要编写一个为您的电台定制的程序或脚本,该程序或脚本与 Liquidsoap 接口。
通过 telnet 连接到 Liquidsoap,如下所示
telnet localhost 1234
连接后,您可以使用以下命令请求歌曲,其中 uri
是系统上音频文件的绝对路径或互联网上音频文件的 URL
request.push uri
要跳过当前播放的歌曲并立即播放下一首歌曲,只需键入 skip
。
有关所有可用命令的列表,请键入 help
,或者键入 help
后跟命令名称以获取有关特定命令的使用信息。
要结束会话,请键入 quit
。
除了 Liquidsoap 的 telnet 接口外,Icecast 还具有一个基于 Web 的管理界面,您可以使用该界面查看听众统计信息、终止 Liquidsoap 的流或在挂载点之间移动听众。在 http://example.com:8000/admin(其中 example.com 是您服务器的完全限定域名)访问它。使用您在 icecast.xml 中设置的 admin-user 和 admin-password。
至此,您现在拥有了一个功能齐全的流媒体服务器,应该可以满足大多数用户的需求。但是,Liquidsoap 非常灵活,允许为特殊用例进行更奇特的设置。请参阅 Liquidsoap 文档 以获取有关可能对您有用的其他语言功能的信息。