问题描述
有没有办法将声卡的实时输出从我们的12.04.1 LTS amd64桌面流式传输到我们网络中的DLNA-compliant外部设备?使用Rygel,miniDLNA和uShare选择共享目录中的媒体内容总是很好 – 但到目前为止,我们完全无法通过DLNA向客户端获取实时音频流。
Pulseaudio声称有一个DLNA /UPnP媒体服务器,与Rygel一起应该这样做。但我们无法让它运行。
我们遵循live.gnome.org,this answer中列出的步骤,以及另一个similar guide中列出的步骤。
在12.04 LTS中,我们可以在DLNA客户端中选择本地音频设备或我们的GST-Launch流,但Rygel显示以下消息,并且客户端声明它到达播放列表的末尾:
(rygel:7380): Rygel-WARNING **: rygel-http-request.vala:97: Invalid seek request
无法在客户端上收听实时音频流。
只有在分发升级到14.04 LTS之后,我们才能从设置很好的outlined in below answer中选择我们的DLNA渲染器上的实时流。仍然,我们需要在启动rygel之后选择已建立的流,并且无法将新流推送到我们的UPnP设备。音频元数据未传输。
有没有其他选择将我们的声卡的音频作为实时流发送到DLNA客户端?
最佳解决方法
Pulseaudio-DLNA
我创建了一个小型服务器,可以发现网络中的所有upnp渲染器,并将它们作为接收器添加到pulseaudio。因此,您可以通过pavucontrol控制每个应用程序在您的upnp设备上播放。
这是我在linux下处理upnp设备时一直想要的那种舒适感。
应用程序可以从源代码或DEB包downloadable from git安装,或者在我们将项目的官方ppa:qos/pulseaudio-dlna添加到我们的源代码后:
sudo apt-get update && sudo apt-get install pulseaudio-dlna
然后,我们从命令行运行pulseaudio-dlna,其中包含以下选项:
pulseaudio-dlna [--host <host>] [--port <port>] [--encoder <encoder>] [--renderer-urls <urls>] [--debug]
pulseaudio-dlna [-h | --help | --version]
有关更多信息,另请参阅pulseaudio-dlna “About”。
当存在DLNA渲染器时,我们可以从声音菜单中选择它作为输出接收器:
次佳解决方法
Pavucontrol是这个拼图游戏中缺少的项目!我也正确设置了一切,外部设备(LG电视)显示声音正在播放,但我没有听到任何声音。今天我安装了pavucontrol,当我打开它时,我找到了通过DLNA服务器引导声音的选项。仅当播放器向pulseaudio输出声音时,才会显示DLNA选项。
第三种解决方法
对不起,我根本无法帮助你使用Rygel,但可能有一个替代方案可能适合你。
原理是获取一个程序将流记录到audiofile,然后使用指向流所在目录的自定义配置启动miniDLNA。
示例:假设我们在〜/stream /中工作。创建〜/stream /minidlna.conf
network_interface=wlan0
media_dir=/home/<user>/stream/
friendly_name=Live Audio Stream
db_dir=/home/<user>/stream/
album_art_names=Cover.jpg/cover.jpg/AlbumArtSmall.jpg/albumartsmall.jpg/AlbumArt.jpg/albumart.jpg/Album.jpg/album.jpg/Folder.jpg/folder.jpg/Thumb.jpg/thumb.jpg
inotify=no
enable_tivo=no
strict_dlna=no
notify_interval=900
serial=12345678
model_number=1
然后将流保存到该目录中的audiofile。谷歌搜索“FFmpeg记录声卡音频”产生了这个命令
ffmpeg -f alsa -i default -acodec flac ~/stream/OutputStream.flac
但我没有太多运气。另一个选择是vlc,你有一个GUI可用,但这不起作用。
然后在另一个终端窗口中启动miniDLNA:
minidlna -d -f ~/stream/minidlna.conf -P ~/stream/minidlna.pid
它应该找到OutputStream.flac,然后可以从您的网络设备访问。
希望如果你还没有解决它给你一些想法。
第四种方法
我必须将“我听到的”流式传输到DLNA渲染器(如WDTV)的一个想法是使用VLC作为http流服务流,并将pulse://alsa_output.xxx.monitor
作为输入,并将其转码为MP3或FLAC。然后我想使用一些DLNA控制点让渲染器播放taht流。 VLC确实正确地为转码流提供服务,但它不允许设置mime类型,因此渲染器拒绝播放它。
接下来的想法是在python中编写一个http服务器来代替服务流。它使用parec
从脉冲获取音频流,使用flac
(或lame
或您想要的任何内容)对其进行编码,并正确设置mime类型。
它适用于以下(非常简单)脚本:
#!/usr/bin/python
import BaseHTTPServer
import SocketServer
import subprocess
PORT = 8080
# run "pactl list short |grep monitor" to see what monitors are available
# you may add a null sink for streaming, so that what is streamed is not played back locally
# add null sink with "pactl load-module module-null-sink"
MONITOR = 'null.monitor'
MIMETYPE = 'audio/flac'
ENCODER = 'flac - -c --channels 2 --bps 16 --sample-rate 44100 --endian little --sign signed'
BUFFER = 65536
class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_HEAD(s):
print s.client_address, s.path, s.command
s.send_response(200)
s.send_header('content-type', MIMETYPE)
s.end_headers()
def do_GET(s):
s.do_HEAD()
pa = subprocess.Popen('parec -d {} | {}'.format(MONITOR, ENCODER), shell = True, bufsize = BUFFER, stdout = subprocess.PIPE)
while True:
data = pa.stdout.read(1024)
if len(data) == 0: break
s.wfile.write(data)
print 'stream closed'
httpd = SocketServer.TCPServer(("", PORT), Handler)
print "listening on port", PORT
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
httpd.server_close()
调整参数,运行它,并将DLNA渲染器指向您的机器。它适用于我的WDTV作为渲染器和带有BubbleUPnP作为控制点的Android手机(您可以在手动将新项目添加到播放列表时输入流URL)。但它应该适用于任何DLNA兼容设备。
第五种方法
注意:此解决方案有效,但Massimo已提出newer and probably better solution。
以下是Ubuntu 14.04(也经过测试并在15.04上工作)的答案,完整性:
-
安装任何所需的包:
sudo apt-get install rygel rygel-preferences rygel-gst-launch
-
创建包含以下内容的文件
~/.config/rygel.conf
:[GstLaunch] enabled=true title=@REALNAME@'s stream launch-items=myaudioflac;myaudiompeg myaudioflac-title=FLAC audio on @HOSTNAME@ myaudioflac-mime=audio/flac myaudioflac-launch=pulsesrc device=upnp.monitor ! flacenc quality=8 myaudiompeg-title=MPEG audio on @HOSTNAME@ myaudiompeg-mime=audio/mpeg myaudiompeg-launch=pulsesrc device=upnp.monitor ! lamemp3enc target=quality quality=6 [Playbin] enabled=true title=Audio/Video playback on @REALNAME@'s computer [general] interface= upnp-enabled=true [MediaExport] uris=
-
从命令行执行以下命令(如果需要,可以将这些命令放入脚本中):
pactl load-module module-http-protocol-tcp pactl load-module module-rygel-media-server rygel &
-
运行
paprefs
命令,并确保在”Network Server”选项卡上启用(选中)两个DLNA选项。 -
在您的计算机上播放一些音频。运行
pavucontrol
程序,在”Playback”选项卡上,将输出设备更改为“DLNA /UPnP Streaming”。
此时,您应该能够从DLNA客户端(渲染器/控制点)播放MPEG和FLAC流。
注意:您可能需要重新启动计算机(或重新启动脉冲)才能开始工作。
第六种方法
来自Adam的python脚本正是我所需要的。辉煌。带有gst-launch的Rygel不能与我的一个渲染器一起使用,但是这个脚本适用于两者。在我的情况下,我正在从squeezelite(用于squeezebox)输入音频流并发送到渲染器。该脚本也可以原始形式工作,从脉冲音频监视器获取输入,如果需要的话。
对这些知之甚少,我设法对脚本做了一些补充:
i)允许它从shell脚本运行并以SIGTERM /SIGKILL终止(‘except’语句现在包含’systemexit’)
ii)允许脚本停止并重新启动,并且re-use是相同的端口(因为重新启动的脚本往往失败,说如果渲染器仍然打开它就无法打开端口) – (allow_reuse_address = True语句)
iii)创建一个从stdin获取输入的版本,并使用sox对其进行重新采样,以wav格式输出(在端口8082上)
所以我的版本看起来像:
#!/usr/bin/python
import BaseHTTPServer
import SocketServer
import subprocess
PORT = 8082
MIMETYPE = 'audio/x-wav'
BUFFER = 65536
class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_HEAD(s):
print s.client_address, s.path, s.command
s.send_response(200)
s.send_header('content-type', MIMETYPE)
s.end_headers()
def do_GET(s):
s.do_HEAD()
pa = subprocess.Popen('sox -t raw -r 96000 -b 24 -L -e signed -c 2 - -t wav -r 44100 -b 16 -L -e signed -c 2 - ', shell = True, bufsize = BUFFER, stdout = subprocess.PIPE)
while True:
data = pa.stdout.read(1024)
if len(data) == 0: break
s.wfile.write(data)
print 'stream closed'
SocketServer.TCPServer.allow_reuse_address = True
httpd = SocketServer.TCPServer(("", PORT), Handler)
print "listening on port", PORT
try:
httpd.serve_forever()
except (KeyboardInterrupt, SystemExit):
pass
httpd.server_close()