maxhawkins / sc_radio

SuperCollider Internet Radio Station
77 stars 12 forks source link

Low latency alternatives to icecast/darkice? #3

Open osetinsky opened 6 years ago

osetinsky commented 6 years ago

Thanks for opening up this project @maxhawkins – I had been looking for something like this.

A couple questions, keeping in mind this is meant as a starting point for some kind of internet radio.

I'm able to get SC running with audio streaming through my browser, which is great. My goal is to get a synth deployed on the internet and allow it to be modified by http/osc requests in close to as realtime as possible. I'm afraid icecast/darkice are not the right technologies for what I want given the 20-30s of latency I'm experiencing between sending OSC messages to SC and hearing the sound change (and this is within the docker container on my local machine).

  1. Is there a way to get latency down to near realtime, ignoring web requests? I know there are several factors responsible for latency using icecast/darkice. Are these the right technologies if I ultimately do want to (a) accept http requests modifying some parameter of the synth (b) map those to OSC commands and send the OSC messages to SC and (c) have the synth be modified in realtime? Is there a better alternative? I had seen something called vban suggested. This does seem a little farfetched but I'm hoping I'm wrong.

this post advises against icecast/darkice for what i want: https://stackoverflow.com/questions/17133689/high-audio-latency-with-icecast-and-darkice

  1. how could audio be streamed/consumed headlessly, e.g. within a mobile game?

@artemkloko @mrtnmgs @azimut @crucialfelix I thought I'd tag you on this since you all wrote in on this repo's one and only issue: https://github.com/maxhawkins/sc_radio/issues/1

Also, here is some SC code/music I wrote. Some better than others...audio mastering is tricky in SC: https://github.com/keypulsations/variations https://soundcloud.com/keypulsations/sets/synth-definitions-1

maxhawkins commented 6 years ago

Maybe see if you can hook up SC to a WebRTC media server like Medooze, MediaSoup, or Janus. WebRTC is better suited for realtime audio.

I don't know Supercollider well enough to know how to connect the two. Most of those media servers can take an Opus-encoded RTP stream as input and stream it out to clients in near-realtime. You'd need to get SC to produce one of those streams.

You might end up having to write/use a Jack or ALSA driver because I think that's the only way to get sound out of Supercollider. Check out how darkice does it. They have a JACK DspSource that pulls the samples from the audio interface and an ogg/vorbis encoder to transcode the resulting samples.

maxhawkins commented 6 years ago

Check out trx "a simple toolset for broadcasting live audio from Linux"

You could combine this with WebRTC to get near-realtime audio from SC in browsers and mobile devices.

osetinsky commented 6 years ago

Appreciate the quick response @maxhawkins – I was reading about opus the other day and jack/alsa came up in discussions I had with @rukano who was working on an SC-based Alexa app

osetinsky commented 6 years ago

I'll let you know what I find 👍

zsaraf commented 5 years ago

@osetinsky did you end up coming up with a good solution? Trying to do the same thing :)

maxhawkins commented 5 years ago

I think trx with an Alsa loopback device is the way to go.

The other piece is broadcasting the RTP stream via WebRTC. I contribute to a WebRTC framework called Pion that you could use to write the WebRTC piece. If I have time I might write a demo and post it here.

osetinsky commented 5 years ago

@zsaraf @maxhawkins i was able to get the ALSA/TRX side of things up and running on AWS, but it wasn't so straightforward because the audio dependencies (for good reason) aren't available on your typical elasticbeanstalk or EC2 instance. I can revisit what I did and let you know what my approach was when I have time this week.

So yes, I'm basically at the WebRTC / media server stage, but there seem to be a lot of options. Janus seemed like a good, light option, but I'll be checking out Pion. I've enjoyed working with golang recently so that's exciting to hear about.

@zsaraf this was available, but my guess is that it'll be high latency https://github.com/Magicking/supercollider-streaming

@maxhawkins i'd appreciate a Pion demo as it relates to this if you're interested in working on that. btw your Dialup app is pretty sweet 👌

maxhawkins commented 5 years ago

@osetinsky Yeah, I forgot this is more complicated than I thought because of kernel modules. What did you end up doing to get TRX working in Docker?

Once I get that working again I can set up the WebRTC side pretty easily.

osetinsky commented 5 years ago

Okay, I had a bit of time to revisit. @zsaraf I pointed @maxhawkins to a dockerfile written by @hairyhenderson for a project he was working on involving routing audio with trx to some raspberry pis:

https://hub.docker.com/r/hairyhenderson/trx/dockerfile/ https://github.com/hairyhenderson/radiorelay https://github.com/hairyhenderson/radiorelay/blob/master/docker-compose.yml

I reached out to him and he mentioned that soundcards and alsa were indeed his biggest challenges.

Since my goal was to test this over the public internet, I wanted to get trx running on an ec2 instance. Following this tutorial, I was getting modprobe: FATAL: Module snd-aloop not found in directory ... errors when running modprobe snd-aloop

After a bit of research, I realized I needed to modify the default kernel boot item. This post was helpful: https://stackoverflow.com/questions/49538514/sound-driver-snd-aloop-kernel-module-setup-issue-with-aws-ec2-ubuntu-16-04-ins

You need to:

  1. edit default grub file vim /etc/default/grub setting GRUB_DEFAULT="1>2"
  2. Run update-grub
  3. reboot
  4. run uname -a to test (you should see something like Linux ip-xxx 4.15.0-44-generic #47-Ubuntu SMP Mon Jan 14 11:26:59 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux)

At this point, after uploading a test sound file, I'm able to use the dummy soundcard:

ubuntu@ip-xxx:~$ ls
bach.wav
ubuntu@ip-xxx:~$ aplay -vv -D hw:Loopback,0 bach.wav
Playing WAVE 'bach.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
Hardware PCM card 0 'Loopback' device 0 subdevice 0
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 6755399441055744000
  appl_ptr     : 0
  hw_ptr       : 0
###########################   +                    | 59%

trx still hasn't come into play yet, but it's installed:

root@ip-xxx:/home/ubuntu# rx
trx (C) Copyright 2012 Mark Hills <mark@xwax.org>
snd_pcm_hw_params_set_buffer_time_max: Invalid argument
root@ip-xxx:/home/ubuntu#

following the trx tutorial above, you should be able to send and receive audio with tx/rx between machines with trx installed after modifying your .asoundrc files. I haven't been able to send or even generate any audio that I can hear, but this is where I am

alexhackney commented 5 years ago

Any update? @osetinsky I'm working on a similar project and the best I've come up with is using Sox with netcat or ffmpeg with icecast.

osetinsky commented 5 years ago

@alexhackney I've been chatting with @maxhawkins about this more over the past month

the trx approach proved too painful because of kernel modules

this doesn't address the Supercollider need, but it does get audio streaming to a browser from a local docker container in real time: https://github.com/osetinsky/pulse-streamer

it uses pulse audio, gstreamer and pion webrtc (which max is a contributor for) https://github.com/pion/webrtc

my goal is to get supercollider streaming...i had tried with pulse+jack+gstreamer+pion with no luck. i think pulse may be getting in the way so next step is to remove that and lean on jack/gstreamer with pion https://github.com/osetinsky/pulse-streamer/tree/supercollider-example/examples/supercollider