Skip to main content

Guide

Why?

AVPro is the only video player that supports live streams, but it does not and will not support audio filters per this VRChat Canny. For live-music venues and worlds, who by nature typically care about audio, this is a problem because being able to apply audio effects is a great addition. Many worlds have excellent visuals, world design, detail, etc. but have very basic audio. I hope to share a little knowledge to help with this. For example, it would be nice to have a low-pass filter in a bathroom, or when you approach the main venue area - hearing the bass rumble and increase in volume as you walk up, perfectly fading into full-spectrum audio. With this method, you can apply a limited (8) number of arbitrary effects to your live streams.

Work Around

A very naïve, initial thought it to just have multiple video players, one with full audio, one with filtered audio - but syncing those _perfectly_ would never happen. However, AVPro supports up to 8 audio channels, we can use those to carry other audio. There are many use cases and directions this can go, which I'll only touch on briefly. One use-case is carrying multi-lingual audio streams, where each channel (or pairs if you want stereo) can carry a different language. Another use case could be to use the audio stream to carry data to control lighting, or effects in the world. This book will cover applying a low-pass filter to a third audio channel, as I think that is a common "want" in many music venues. As this is a WIP, I hope to expand this to apply any arbitrary filter to any channel. Side note: I'm told if using RTSP there is a limitation of only 5 channels, so another protocol would need to be used if more is desired. MPEG-2, for example should support all 8 channels that AVPro can handle.

How

Making multi-channel audio streams is a pain unfortunately. Specifically because we want to apply an effect to only select channels, most software doesn't support this. There are two methods this will include, although I'm sure there are more.

Reaper DAW

Using a Digital Audio Workstation program like Reaper is capable of doing this. This a paid product, but has a free trial. During installation there is an optional checkbox to install ReaRoute which is required to make this work. This method required using a custom OBS fork that supports multi-channel audio found here, in conjunction with a custom audio driver ASIO4All, and lastly a plugin for OBS that can take advantage of the ASIO audio source called obs-asio. Make sure to install all of these.

These introduction videos to Reaper multi-channel audio show you pretty much all you need to know to make this happen (pt1 and pt2). Those videos just show simple up-mixing, routing, and typical surround sound features, but to do something like applying an effect to only certain channels is only slightly different. Instead of applying a ReaSurround filter, you can do something like adding a ReaEQ FX on a track, then for example set the "Plugin pin connector" to use channel 1 & 2 as input, and channel 3 & 4 as output. This would: duplicate channel 1&2 to 3&4, and apply whatever EQ effects you have to only channels 3&4. See the image below for an example setup.

lowpass.png 

Then, with ReaRoute, map the channels in Reaper to ReaRoute output "devices" done in the Route button of the Master track.

rearoute_reaper.png

This shows mapping channels "1/2" to ReaRoute 1/ReaRoute 2 and channels "3/4" to ReaRoute 3 / ReaRoute 4. This is about it for Reaper. Next, in the OBS Music Edition, first thing is to make sure you have multiple channels enabled (Settings -> Audio -> Channels), then add a new input, there should now be a source called "ASIO Input Capture". Set the channels/sources accordingly and that should be it. 

obs_rearoute_asio.png

This method is a lot to setup though, but it does work. I would still like to explore using Reaper to just read from a stream and pushing this out another stream i.e. receive a Twitch stream, manipulate audio, and push back out to either Twitch or VRCDN or something else. This method is unsustainable for multi-artist music venues otherwise as it's just not feasible to ask each artist to go through this kind of setup. 

Nginx RTMP

A some-what better solution is to just host your own RTMP server. Part of this WIP is trying to make this as easy to adopt as possible. Although setting up a server is a big ask, very low processing power is needed for simple EQ effects. A Raspberry Pi could handle this with ease. Setting up Nginx is as easy as a few commands as well. The huge benefit of this method is that artists can simply point their OBS towards your server, and everything will just work. I detect no noticeable latency or degradation in anyway by using this "middle man" audio processing. Artists will of course incur a latency penalty from connecting to your server first, just whatever ping time between the artist and the server.

See this tutorial to setup Nginx in depth if you desire (tutorial), but in linux it just boils down to running this:

sudo apt install libnginx-mod-rtmp nginx ffmpeg

Note: ffmpeg version 3.4.8 plays well with VRCDN, but later versions don't. Not sure why, but if using Ubuntu, the default version in 18.04 works, but later version of Ubuntu won't unless you compile yourself.

Nginx setup is very simple, just add this into /etc/nginx/nginx.conf

rtmp {
  server {
    listen 1935;
    ping 30s;
    chunk_size 4096;
    # allow publishing from your own network
    allow publish 192.168.1.0/24;
    # allow publishing from another IP. 
    allow publish 1.2.3.4;
    deny publish all;

    notify_method get;

    application ingest {
      live on;
      allow play all;
      exec /home/username/rtmp/start_stream.sh $name;
      exec_kill_signal term;
      record off;
   }
  }
}

Then the "exec" script is what does the magic. Nginx will execute this script on stream start, and kill it when the stream disconnects. This is very handy. The script it executes:

#!/bin/bash

echo "$(date +"%Y/%m/%d %H:%M:%S"): starting"
# This is ultimately the code that runs on stream stop. This kills all children of this script
on_die() {
  # kill all children
  pkill -KILL -P $$
}
# Nginx will trigger this trap on stream end
trap 'on_die' TERM

# read in raw stream, upmix stereo to 5.1
echo "Upmixing to 5.1 surround and pushing to VRCDN"
ffmpeg -i rtmp://127.0.0.1/ingest/test \
        -err_detect ignore_err \
        -filter_complex "[0:a]pan=5.1(side)|FL=FL|FR=FR|LFE<FL+FR|SL=FL|SR=FR[a]" \
        -map 0 -map -0:a -map "[a]" -ac 6 \
        -c:a aac -c:v copy \
        -f flv rtmp://ingest.vrcdn.live/live/YOURVRCDNKEY &

wait

And that's it! With this example setup, any streamer just points their OBS to rtmp://192.168.1.31/ingest with a stream key of test. You can of course expose this publicly with port forwarding, although I still have yet to look into better security or stream keys. A trustworthy host could set it up so a streamer to use their VRCDN key for your server, and you in turn just push the stream out to that streamers own VRCDN account. Again, this would require trust, or maybe just use revocable guest keys.

Once a streamer hits "start stream" - Nginx will fire off that script, which will read in the streamers stream from the RTMP server, then up mix it to 5.1 surround sound, set the audio channels to 6, and pushes it right back out to VRCDN. Ffmpeg default up-mixing behavior sets the LFE channel to have a low-pass, so there is no need for any extra work in my use case. On my home network, I did not notice any additional latency or any negative effects from this additional processing, which is expected as *-pass filters do not transform any audio data, it only removes a frequency range so very low processing overhead.

Still very much WIP! For my use case, there is only need for 3 channels, so we're wasting some audio bandwidth with the extra ones. Still need to figure out some FFMPEG magic to individually apply filters to channels, so that any filter can be applied. Then how to make this easy/accessible as possible.

Feel free to reach out on discord if you have any questions or input! lightbulb#0004

Additional References:

https://www.digitalocean.com/community/tutorials/how-to-set-up-a-video-streaming-server-using-nginx-rtmp-on-ubuntu-20-04

https://obsproject.com/wiki/Surround-Sound-Streaming-and-Recording