Open anarcat opened 10 years ago
This is not supported for now, unfortunately. I would love to add RTP support but I don't think we've ever come to a library simple enough to be used. Do you know of one that you would recommend?
So far I have used:
cvlc rtp://@224.0.0.56:5004
)mplayer -demuxer rawaudio -rawaudio format=0x20776172 rtp://224.0.0.56:5004
)load-module module-rtp-send source=rtp.monitor port=5004 loop=1
and load-module module-null-sink sink_name=rtp format=s16be channels=2 rate=44100 sink_properties="device.description='RTP Multicast Sink'"
)gst-launch udpsrc multicast-group=224.0.0.56 port=5004 ! "application/x-rtp, media=(string)audio, clock-rate=44100, payload=(int)10" ! rtpL16depay ! audioconvert ! alsasink
)I am guessing gstreamer may be the solution since liquidsoap already supports it, but it doesn't work at all in Debian right now (or is this 1.0?): http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=727044
I am not sure a library would suffice either, as it may not appear as "playing" if no stream is available... I guess this should be tested...
I also think that
input.gstreamer.audio("udpsrc multicast-group=224.0.0.56 port=5004 ! "application/x-rtp, media=(string)audio, clock-rate=44100, payload=(int)10" ! rtpL16depay ! audioconvert")
is the right solution. I am currently using 1.1.1-6 version of liquidsoap in Debian (testing) and just tested that gstreamer is working. I think that Sourcefabric has updated packages for currenst stable Debian here: http://apt.sourcefabric.org/
Okay for that's for listening on a multicast RTP stream, how about generating one?
Also, while this works:
gst-launch udpsrc multicast-group=224.0.0.56 port=5004 ! "application/x-rtp, media=(string)audio, clock-rate=44100, payload=(int)10" ! rtpL16depay ! audioconvert ! alsasink
This doesn't:
liquidsoap 'out(input.gstreamer.audio(pipeline="udpsrc multicast-group=224.0.0.56 port=5004 ! \"application/x-rtp, media=(string)audio, clock-rate=44100, payload=(int)10\" ! rtpL16depay ! audioconvert ! alsasink sync=false"))'
Because:
gst-launch audiotestsrc ! audioconvert ! alsasink
and:
liquidsoap 'out(input.gstreamer.audio(pipeline="audiotestsrc"))'
yield the same result, I would have assumed this would work, but whereas the latter eventually yields:
2014/02/04 23:18:25 [clock.wallclock_pulse:3] Streaming loop starts, synchronized by active sources.
2014/02/04 23:18:25 [mksafe:3] Switch to safe_blank.
2014/02/04 23:18:25 [mksafe:3] Switch to input(dot)gstreamer(dot)audio_video_9110 with transition.
the other never switches to the gstreamer input:
anarcat@marcos:~$ liquidsoap 'out(input.gstreamer.audio(pipeline="udpsrc multicast-group=224.0.0.56 port=5004 ! \"application/x-rtp, media=(string)audio, clock-rate=44100, payload=(int)10\" ! rtpL16depay"))'
ERROR: Could not load classifier cascade /usr/share/opencv/haarcascades/haarcascade_frontalface_alt2.xml
Failed to register plugin /usr/lib/frei0r-1/facedetect.so: Frei0r.Failure
2014/02/04 23:19:06 >>> LOG START
2014/02/04 23:19:06 [protocols.external:3] Found "/usr/bin/wget".
2014/02/04 23:19:06 [main:3] Liquidsoap 1.1.1
2014/02/04 23:19:06 [main:3] Using: graphics=[distributed with Ocaml] pcre=7.0.2 dtools=0.3.1 duppy=0.5.1 duppy.syntax=0.5.1 cry=0.2.2 mm=0.2.1 xmlplaylist=0.1.3 lastfm=0.3.0 ogg=0.4.5 vorbis=0.6.1 opus=0.1.0 speex=0.2.0 mad=0.4.4 flac=0.1.1 flac.ogg=0.1.1 dynlink=[distributed with Ocaml] lame=0.3.2 shine=0.1.1 gstreamer=0.2.0 frei0r=0.1.0 voaacenc=0.1.0 theora=0.3.0 schroedinger=0.1.0 gavl=0.1.5 bjack=0.1.4 alsa=0.2.1 ao=0.2.0 samplerate=0.1.2 taglib=0.3.1 magic=0.7.3 camomile=0.8.4 inotify=1.0 faad=0.3.2 soundtouch=0.1.7 portaudio=0.2.0 pulseaudio=0.1.2 ladspa=0.1.4 dssi=0.1.1 sdl=0.9.1 camlimages=4.0.0 lo=0.1.0 yojson=1.1.7 gd=1.0a5
2014/02/04 23:19:06 [dynamic.loader:3] Could not find dynamic module for fdkaac encoder.
2014/02/04 23:19:06 [dynamic.loader:3] Could not find dynamic module for aacplus encoder.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/mad.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/shine.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/frei0r.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/oss.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/ao.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/ladspa.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/ogg.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/dssi.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/pulseaudio.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/bjack.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/speex.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/xmlplaylist.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/samplerate.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/soundtouch.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/gavl.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/portaudio.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/theora.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/vorbis.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/taglib.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/lo.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/lame.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/gstreamer.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/camlimages.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/flac_ogg.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/cry.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/voaacenc.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/sdl.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/opus.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/graphics.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/flac.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/faad.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/schroedinger.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/gd.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/alsa.cmxs.
2014/02/04 23:19:06 [dynamic.loader:2] Loaded plugin file /usr/lib/liquidsoap/1.1.1/plugins/lastfm.cmxs.
2014/02/04 23:19:06 [frame:3] Using 44100Hz audio, 25Hz video, 44100Hz master.
2014/02/04 23:19:06 [frame:3] Frame size must be a multiple of 1764 ticks = 1764 audio samples = 1 video samples.
2014/02/04 23:19:06 [frame:3] Targetting 'frame.duration': 0.04s = 1764 audio samples = 1764 ticks.
2014/02/04 23:19:06 [frame:3] Frames last 0.04s = 1764 audio samples = 1 video samples = 1764 ticks.
2014/02/04 23:19:06 [threads:3] Created thread "generic queue #1".
2014/02/04 23:19:06 [threads:3] Created thread "generic queue #2".
2014/02/04 23:19:06 [threads:3] Created thread "wallclock_pulse" (1 total).
2014/02/04 23:19:06 [clock.wallclock_pulse:3] Streaming loop starts, synchronized by active sources.
2014/02/04 23:19:06 [mksafe:3] Switch to safe_blank.
oh oh oh, i found it:
liquidsoap 'out(input.gstreamer.audio(pipeline="udpsrc multicast-group=224.0.0.56 port=5004 caps=\"application/x-rtp, media=(string)audio, clock-rate=44100, payload=(int)10\" ! rtpL16depay"))'
i was missing the caps=
bit, which seems to be optional on the commandline! --debug
helped quite a bit in debugging that.
And now it works and fallbacks as well! ie. this also works:
rtpsrc = input.gstreamer.audio(pipeline="udpsrc multicast-group=224.0.0.56 port=5004 caps=\"application/x-rtp, media=(string)audio, clock-rate=44100, payload=(int)10\" ! rtpL16depay")
security = single('/srv/mp3/misc/smash.mp3')
radio= fallback([rtpsrc,security])
out(radio)
Unfortunately the fallback starts first, and there's a ~5 seconds delay when the rtp stream goes blank, but it works.
I also found out how to produce the RTP stream, so here's everything from the top:
liquidsoap 'output.gstreamer.audio(single("/srv/mp3/misc/smash.mp3"), pipeline="audioconvert ! rtpL16pay ! udpsink host=224.0.0.56 auto-multicast=true port=5004")'
liquidsoap 'out(input.gstreamer.audio(pipeline="udpsrc multicast-group=224.0.0.56 port=5004 caps=\"application/x-rtp, media=(string)audio, clock-rate=44100, payload=(int)10\" ! rtpL16depay"))'
boo-ya. i guess we can close this now, although having that documentation somewhere would just rock.
So while this works in and out, it won't work with VLC or other clients, because the udpsink doesn't seem to send SDP announcements to describe the stream. VLC complains with:
anarcat@marcos:~$ cvlc rtp://@224.0.0.1:5004
VLC media player 2.1.2 Rincewind (revision 2.1.2-0-ga4c4876)
[0x1ac9588] dummy interface: using the dummy interface module...
[0x7eff48000e28] rtp demux error: unspecified payload format (type 96)
[0x7eff48000e28] rtp demux: A valid SDP is needed to parse this RTP stream.
[0x7eff48000e28] main demux error: SDP required
[0x7ff7c4000e38] main demux error: A description in SDP format is required to receive the RTP stream. Note that rtp:// URIs cannot work with dynamic RTP payload format (96).
The fix is of course to work pulseaudio:
output.pulseaudio(final)
and then set a default sink in PA:
# we need the following config appended to a default.pa:
load-module module-null-sink sink_name=rtp format=s16be channels=2 rate=44100 sink_properties="device.description='RTP Multicast Sink'"
load-module module-rtp-send source=rtp.monitor port=5004 destination_ip=224.0.0.1 loop=1
set-default-sink rtp
What's the status here? I the recipe stable enough? If so, could you please document it as an extra page in doc/content and create a pull request?
the recipe works, but i have given up on the whole stack because of latency problems after an upgrade to debian jessie... not sure what happened there. the jukebox is just turned off now... but my last comment here worked and could be reused.
According to this documentation , you need to create a .sdp file and open that in VLC:
v=0 m=video 5000 RTP/AVP 96 c=IN IP4 127.0.0.1 a=rtpmap:96 MP4V-ES/90000
While that's for video, perhaps if you change it for audio it might work? I'm gonna give this a try. I'd like Airtime to have a low latency stream back to our station.
for the record, i turned off RTP here because of the interference it does over wifi - it completely destroys the network here...
I have come to like RTP to produce a low-latency, high quality (but incidentally high bandwidth) stream within the house. I currently use MPD to stream audio to icecast and RTP, as described here. I know I can make liquidsoap stream to/from icecast fairly easily, but then I can't make it stream RTP in a meaningful way. I have tried various hacks with mplayer, pipes and all sorts of hacks, but couldn't get anything reliable going.