<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"
    xmlns:fh="http://purl.org/syndication/history/1.0"
    xmlns:at="http://purl.org/atompub/tombstones/1.0">

    <title>Sockpuppet: Blog</title>
    
    <subtitle><![CDATA[Updates, articles, and behind-the-scenes content.]]></subtitle>
    
    <link href="https://sockpuppet.band/blog/feed?id=1743&amp;tag=vrchat" rel="self" />
    
    <link href="https://sockpuppet.band/blog/feed?tag=vrchat" rel="current" />
    <fh:archive/>
    

    <link href="https://busybee.superfeedr.com" rel="hub" />
    
    
    <link href="https://sockpuppet.band/blog/" />
    <id>tag:sockpuppet.band,2026-05-14:blog</id>
    <updated>2026-01-24T09:00:00-08:00</updated>

    

    <entry>
        
        <title>VR performance setup 2.0</title>
        <link href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0" rel="alternate" type="text/html" />
        <published>2026-01-24T09:00:00-08:00</published>
        <updated>2026-01-24T09:00:00-08:00</updated>
        <id>urn:uuid:8aa1a45d-401a-4fca-946a-0d3bb2282908</id>
        <author><name>fluffy</name></author>
        <summary type="html"><![CDATA[<p>Last September I <a href="https://sockpuppet.band/blog/3183-VR-performance-stuff">wrote about my VRChat performance setup</a>, based on some new changes I was trying in order to do more to integrate backing tracks into my performances. I quickly ran into some limits with the approach I was taking, and have ended up completely changing how I do things since then, with a setup that is much more reliable, more capable, and higher-quality. It also allows me to use the same audio setup for both mic-boosted and streamed performances.</p>]]></summary>
        <content type="html"><![CDATA[

		

        



        <p>Last September I <a href="https://sockpuppet.band/blog/3183-VR-performance-stuff">wrote about my VRChat performance setup</a>, based on some new changes I was trying in order to do more to integrate backing tracks into my performances. I quickly ran into some limits with the approach I was taking, and have ended up completely changing how I do things since then, with a setup that is much more reliable, more capable, and higher-quality. It also allows me to use the same audio setup for both mic-boosted and streamed performances.</p><p>So here&rsquo;s how my performing setup works!</p>

        
            <h3 id="1302_h3_1_The-hardware-side">The hardware side<a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0#1302_h3_1_The-hardware-side" class="toc_link"></a></h3><p>Previously I was using an amalgam of the built-in mic on my headset, the line input on my onboard audio, and VoiceMeeter to tie everything together. Unfortunately, this setup had some pretty severe limitations, especially when it came to managing latency (particularly with backing tracks), as well as being able to add live effects to the signal chain. It also led to some embarrassing situations where my audio would go haywire due to a connector coming loose or the like.</p><p>A few years ago, I upgraded my recording studio from a <a href="https://amzn.to/45nyC6M">Focusrite Scarlett 18i8</a> to an <a href="https://amzn.to/3O0zxnw">18i20</a>, so I had this spare 18i8 just sitting around. I was using it on my office computer (where I do my video editing and programming), but it was massive overkill for those needs, and I came to realize it works much better for my performance setup instead. So now I have a plain old <a href="https://amzn.to/4rghvwe">headphone amp</a> in the office, and the 18i8 is on my VR computer.</p><p>The 18i8 has a handy feature where you can set up multiple output/monitor submixes, so for example you can have different audio levels of different things going to the headphones, the line outputs, and so on. It also has a built-in &ldquo;loopback&rdquo; interface, where you can give it a monitor mix that then appears as a standard audio input to the computer. These features are <em>extremely</em> useful for this use case (as well as any other live performance or studio recording situation).</p><p>I have the following connections:</p>
<ul>
<li>Front input 1: My microphone (I currently switch between an MXL condenser mic and an Electro-Voice dynamic depending on my mood and what&rsquo;s sounding better at the moment)</li>
<li>Front input 2: My guitar signal chain</li>
<li>Headphone output 1: a <a href="https://amzn.to/4pSp7nj">LEKATO Wireless IEM system</a> (which in turn connects to <a href="https://amzn.to/3YWnHxi">some old 3.5mm Apple earbuds</a>, which give me a nice balance of size and audio quality; there are better ones to buy new but I had these lying around from some old iPhone or something)<sup id="r_e1302_fn1"><a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0#d_e1302_fn1" rel="footnote">1</a></sup></li>
<li>Headphone output 2: my <a href="https://www.musiciansfriend.com/amplifiers-effects/zt-lunchbox-junior-guitar-combo-amp/h82899000001000">tiny lunchbox amp</a></li>
<li>My <a href="https://www.tcelectronic.com/product.html?modelCode=0828-AAH">reverb unit</a>, with its inputs on the 18i8&rsquo;s Line 1-2 outputs, and its outputs on the 18i8&rsquo;s Line 5-6 inputs</li>
<li>Front input 3 and 4: Available for other instruments (sometimes I plug my <a href="https://amzn.to/4aabmvv">digital piano</a> in there, for example)</li>
</ul>
<p>I have the reverb unit set to 100% wet, so that it is only being used as a bus send. I also have a bypass toggle pedal so that I can cut to a purely dry signal when needed (such as in <a href="https://sockpuppet.band/track/a-long-plastic-hallway">A Long Plastic Hallway</a>, which uses lack-of-reverb as an effect for emphasis).</p><h3 id="1302_h3_2_Mix-setup">Mix setup<a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0#1302_h3_2_Mix-setup" class="toc_link"></a></h3><p>First, I use the <a href="https://support.focusrite.com/hc/en-gb/articles/11064999655314-Adding-multiple-inputs-in-streaming-software-on-Windows-using-Loopback">multiple input functionality</a> to provide Windows audio devices for all of the necessary channels.</p>
<figure class="images"><a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0"><img src="https://sockpuppet.band/static/_img/8e/d9f1/18i8-multiple-inputs_7aaae6df3e_364x260_q50.webp" width="364" height="260" srcset="https://sockpuppet.band/static/_img/8e/d9f1/18i8-multiple-inputs_7aaae6df3e_364x260_q50.webp 1x, https://sockpuppet.band/static/_img/8e/d9f1/18i8-multiple-inputs_7aaae6df3e_q50.webp 2x" loading="lazy" class="u-photo" alt="A window showing all of the Focusrite inputs separated out"></a></figure>
<p>Windows 10 and 11 also have a feature where you can assign arbitrary labels to your audio inputs and outputs; I use this to give the following names to the playback channels:</p>
<ul>
<li>Playback 1+2: Playback</li>
<li>Playback 3+4: Game audio</li>
<li>Playback 5+6: Control room</li>
</ul>
<p>and I also set labels on my VR headset&rsquo;s microphone and speakers, just to make them easier to keep track of.</p>
<figure class="images"><a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0"><img src="https://sockpuppet.band/static/_img/6a/8d6a/18i8-output-labels_b350ce5fcc_640x489_q50.webp" width="640" height="489" srcset="https://sockpuppet.band/static/_img/6a/8d6a/18i8-output-labels_b350ce5fcc_640x489_q50.webp 1x, https://sockpuppet.band/static/_img/6a/8d6a/18i8-output-labels_b350ce5fcc_1280x978_q50.webp 2x" loading="lazy" class="u-photo" alt="Windows 11 control panel showing helpful output labels"></a></figure>
<p>In Focusrite Control I have separate submixes for all three of the outputs, as well as the loopback interface.</p>
<figure class="images"><a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0"><img src="https://sockpuppet.band/static/_img/de/6045/18i8-monitor-mix_dd413feaa9_640x489_q50.webp" width="640" height="489" srcset="https://sockpuppet.band/static/_img/de/6045/18i8-monitor-mix_dd413feaa9_640x489_q50.webp 1x, https://sockpuppet.band/static/_img/de/6045/18i8-monitor-mix_dd413feaa9_1280x978_q50.webp 2x" loading="lazy" class="u-photo" alt="Focusrite Control UI showing the monitor mix for headphone 1"></a></figure>
<p>Headphone 1 gets the monitor mix that goes to my IEMs. It receives all of the input channels, as well as all three<sup id="r_e1302_fn2"><a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0#d_e1302_fn2" rel="footnote">2</a></sup> &ldquo;Playback&rdquo; channels (which are used to route multiple separate software outputs into separate mixes).</p><p>Headphone 2 gets the same, minus the microphone (to avoid feedback), and is connected to the line input on my lunchbox amp.<sup id="r_e1302_fn3"><a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0#d_e1302_fn3" rel="footnote">3</a></sup></p><p>Line 1-2 (reverb send) gets just the instruments; I bake the reverb into my backing tracks.</p><p>Loopback gets the mix that goes out to the stream and/or world.</p><h3 id="1302_h3_3_Software-setup">Software setup<a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0#1302_h3_3_Software-setup" class="toc_link"></a></h3><p>Unlike before, I do not need Voicemeeter, and I do not even have it installed anymore, as all of the audio that goes to the stream is now handled by the 18i8, and I do not need to mix anything into or from my VR headset.</p><p>I have configured VLC (which I use for playing my backing tracks) to output to the Playback 1+2 device by default.</p><h4 id="1302_h4_4_OBS-setup">OBS setup<a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0#1302_h4_4_OBS-setup" class="toc_link"></a></h4><p>OBS allows you to set up multi-channel audio recording. I set OBS to use channel 1 in the stream, and to record all 6 channels to separate tracks in my local recording. Then I have the following audio input sources:</p>
<table>
<thead>
<tr>
<th>Input name</th>
<th>Source name</th>
<th>OBS output track</th>
<th>Video audio channel</th>
</tr>
</thead>

<tbody>
<tr>
<td>Loopback</td>
<td>Live mix</td>
<td>1</td>
<td>1+2</td>
</tr>
<tr>
<td>Input 1-2</td>
<td>Mic + guitar</td>
<td>2</td>
<td>3+4</td>
</tr>
<tr>
<td>Input 3-4</td>
<td>Piano</td>
<td>3</td>
<td>5+6</td>
</tr>
<tr>
<td>Input 5-6</td>
<td>Reverb</td>
<td>3</td>
<td>5+6</td>
</tr>
<tr>
<td>Headset mic</td>
<td>Headset mic</td>
<td>5 (panned left)</td>
<td>9</td>
</tr>
</tbody>
</table>
<p>As well as the following audio output captures:</p>
<table>
<thead>
<tr>
<th>Output name</th>
<th>Source name</th>
<th>OBS output track</th>
<th>Video audio channel</th>
</tr>
</thead>

<tbody>
<tr>
<td>Headset speakers</td>
<td>Headset speakers</td>
<td>5 (panned right)</td>
<td>10</td>
</tr>
<tr>
<td>Playback 1+2 (playback)</td>
<td>Backing track</td>
<td>4</td>
<td>7+8</td>
</tr>
<tr>
<td>Playback 3+4 (game audio)</td>
<td>Game audio</td>
<td>6</td>
<td>11+12</td>
</tr>
<tr>
<td>Playback 5+6 (control room)</td>
<td>Control room</td>
<td>5 (panned right)</td>
<td>10</td>
</tr>
</tbody>
</table>
<p>Finally, I have a bunch of visuals set up; mostly this is <a href="https://github.com/Off-World-Live/obs-spout2-plugin">Spout2</a> to capture my in-game streaming camera, and <a href="https://github.com/phandasm/waveform">Waveform</a> to let me do various audio visualizers in varying combinations.</p><h4 id="1302_h4_5_Mic-boosted-performances">Mic boosted performances<a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0#1302_h4_5_Mic-boosted-performances" class="toc_link"></a></h4><p>When doing a mic boosted performance, I set my system audio output to Playback 3+4 (Game Audio) and VRChat&rsquo;s audio input to Loopback. This way, my full final audio mix goes to my VRChat microphone, and I hear the game in my IEMs. My backing track works the same as anywhere else.</p><p>The one downside to this setup is that my lip sync will also follow my instruments and backing track, but there&rsquo;s not a lot I can do about that aside from adding face tracking to my VR setup.</p><p>If I want to record my performance, I launch OBS and set it to record. OBS is not involved in the signal chain going to the world at all.</p><h4 id="1302_h4_6_Streamed-performances">Streamed performances<a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0#1302_h4_6_Streamed-performances" class="toc_link"></a></h4><p>Most streamed performances involve a Discord voice call for coordinating between the show runners and the performers. This is where the &ldquo;control room&rdquo; channel comes in; I set Discord&rsquo;s voice to use my VR headset&rsquo;s microphone as input, and Playback 5+6 as speakers. This way the voice chat only hears my voice (rather than all of my instruments), and I can hear anything they say on my IEMs. The Discord call gets recorded to track 5, with the left channel being me and the right channel being everyone else.</p><p>Otherwise, my audio setup is as follows:</p>
<ul>
<li>System audio to Playback 3+4</li>
<li>VRChat microphone is the VR headset mic (so it gets clean lipsync)</li>
<li>And I set VRChat&rsquo;s &ldquo;microphone output level&rdquo; to 0%, so that my camera can see my lips move but the audio doesn&rsquo;t go out into the world<sup id="r_e1302_fn4"><a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0#d_e1302_fn4" rel="footnote">4</a></sup></li>
</ul>
<p>As far as running the stream itself goes, typically I stream either to <a href="https://live.sockpuppet.band/">my Owncloud instance</a> or to <a href="https://vrcdn.live/">VRCDN</a> depending on the needs of the show. Larger shows provide their own streaming ingest.</p>
<ul>
<li>Owncloud lets me serve an absolute crapton of viewers (thanks in part to my <a href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN">overly-complicated CDN setup</a>), but it&rsquo;s not allowed as a stream source by default in VRChat so people need to enable untrusted URLs. It also tends to be pretty high in latency, usually on the order of 6-10 seconds.</li>
<li>VRCDN limits me to 40 concurrent viewers, but the latency is pretty low (usually 1-2 seconds). This is fine for smaller shows, and many showrunners will restream my VRCDN stream into the world with their own visuals overlaid on top anyway, which also adds some latency.</li>
<li>Larger music festivals (such as <a href="https://sockpuppet.band/live/?tag=VRelium">VRelium</a>) will provide their own ingest server and stream management.</li>
</ul>
<h4 id="1302_h4_7_Editing-recordings">Editing recordings<a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0#1302_h4_7_Editing-recordings" class="toc_link"></a></h4><p>And now the really nice thing about this setup is that I can do some audio editing and remixing in retrospect. I do most of my video editing in <a href="https://www.blackmagicdesign.com/products/davinciresolve">DaVinci Resolve</a>, which has pretty good multichannel audio support.</p><p>By default, the video will be pulled in with the following stereo audio tracks:</p>
<table>
<thead>
<tr>
<th>Track</th>
<th>Channels</th>
<th>Contents</th>
</tr>
</thead>

<tbody>
<tr>
<td>1</td>
<td>1+2</td>
<td>Live mix</td>
</tr>
<tr>
<td>2</td>
<td>3+4</td>
<td>Mic (left) + guitar (right)</td>
</tr>
<tr>
<td>3</td>
<td>5+6</td>
<td>Piano + reverb</td>
</tr>
<tr>
<td>4</td>
<td>7+8</td>
<td>Backing track</td>
</tr>
<tr>
<td>5</td>
<td>9+10</td>
<td>Headset mic (left) + Discord call (right)</td>
</tr>
<tr>
<td>6</td>
<td>11+12</td>
<td>Game audio/audience</td>
</tr>
</tbody>
</table>
<p>Typically what I&rsquo;ll do is separate out the audio tracks from the video, and I&rsquo;ll shift track 6 back to compensate for the latency between me and the audience. For mic-boost performances this isn&rsquo;t much (usually under a second) and can usually be ignored, but for streamed performances this will be multiple seconds (often on the order of 20 or more!) and this is especially important during those magical times when people either respond to my banter or sing along with me! (The latter happens with the call-and-response bits in <a href="https://sockpuppet.band/track/safety-in-numbers">Safety In Numbers</a>, and it fills me with warm fuzzies every time.)</p><p>If the track 1 (live mix) audio is fine, I&rsquo;ll use it and track 6 directly, and mute the other tracks. However, sometimes I need to get fancy and change the mix in retrospect. In that case, I&rsquo;ll change my audio tracks as such:</p>
<ul>
<li>Audio 1: Stereo, using channels 1+2 (live mix)</li>
<li>Audio 2: Mono, using channel 3 (voice)</li>
<li>Audio 3: Mono, using channel 4 (guitar)</li>
<li>Audio 4: Stereo, using channels 5+6 (reverb, and piano if I happened to use it)</li>
<li>Audio 5: Stereo, using channels 7+8 (backing track)</li>
<li>Audio 6: Stereo, using channels 12+11 (game audio, swapped to present it from the audience&rsquo;s POV)<sup id="r_e1302_fn5"><a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0#d_e1302_fn5" rel="footnote">5</a></sup></li>
</ul>
<p>In this situation, I&rsquo;ll mute tracks 2-4, and use track 1 to line up tracks 5 and 6, which will have differing amounts of latency. Then I&rsquo;ll mute track 1 and unmute 2-4, and then adjust my recorded mix as necessary.</p><p>Track 6 in particular needs to be lined up pretty carefully, as OBS captures outputs with no latency at all, but inputs get about 300ms of latency due to limitations in Windows audio. In theory I could have OBS add 300ms or so of latency to the output capture, but it&rsquo;s fiddly and I&rsquo;d still need to adjust things anyway, so I&rsquo;d might as well just do it once when I edit.<sup id="r_e1302_fn6"><a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0#d_e1302_fn6" rel="footnote">6</a></sup></p><h3 id="1302_h3_8_Backing-track-playlist-setup">Backing track/playlist setup<a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0#1302_h3_8_Backing-track-playlist-setup" class="toc_link"></a></h3><p>When I&rsquo;m performing there&rsquo;s a lot of stuff to keep track of. If I&rsquo;m only doing 1-2 songs I can load the .wav files into VLC and it&rsquo;s no big deal, but many of my shows are much more complicated and my ADHD brain can only hold so much stuff in my working memory.</p><p>So, I have a <a href="https://www.apple.com/final-cut-pro/">Final Cut Pro</a> library that contains all of my backing tracks; some songs have multiple versions available (e.g. with and without guitar mixed in, or album vs. live versions). In the library files I also have brief version notes and the dominant key signature, and with this I can quickly put together a set list with a reasonable progression and fitting the time constraints.</p><p>A few of the songs also have a lyric display baked in, because try as I might, I just can&rsquo;t memorize <a href="https://sockpuppet.band/releases/tracks?tag=type:lyrical">every song</a><sup id="r_e1302_fn7"><a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0#d_e1302_fn7" rel="footnote">7</a></sup>. For some songs I&rsquo;ll use <a href="https://croonify.com/">Croonify</a> to prepare a synchronized lyric display (replacing Croonify&rsquo;s stem-separated audio with my own clean backing track), but for others I&rsquo;ll just put up some basic text with the necessary cues to keep me from messing up too badly.</p><p>When I prepare my set, I&rsquo;ll also put in a bit of visual stuff for my own reference, such as having it display the title of the next song or little notes like &ldquo;2 songs left&rdquo; or specific banter points I need to hit.</p>
<figure class="images"><a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0"><img src="https://sockpuppet.band/static/_img/ea/897f/backing-track-construction_c83e628945_640x343_q50.webp" width="640" height="343" srcset="https://sockpuppet.band/static/_img/ea/897f/backing-track-construction_c83e628945_640x343_q50.webp 1x, https://sockpuppet.band/static/_img/ea/897f/backing-track-construction_c83e628945_1280x686_q50.webp 2x" loading="lazy" class="u-photo" alt="A screenshot of Final Cut Pro showing a library of songs and a timeline with a show's prepared set"></a></figure>
<p>When I encode the video I&rsquo;ll just use Final Cut&rsquo;s &ldquo;Export File (default)&rdquo; to do a quick lossless encode and then I&rsquo;ll use FFmpeg to encode the final video at a more useful bitrate, with:</p><figure class="blockcode"><pre class="highlight" data-language="bash" data-line-numbers><span class="line" id="e1302cb1L1"><a class="line-number" href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0#e1302cb1L1"></a><span class="line-content">ffmpeg<span class="w"> </span>-i<span class="w"> </span><span class="s2">&quot;2026-02-30 example.mov&quot;</span><span class="w"> </span>-b:a<span class="w"> </span>320k<span class="w"> </span><span class="se">\</span></span></span>
<span class="line" id="e1302cb1L2"><a class="line-number" href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0#e1302cb1L2"></a><span class="line-content"><span class="w">    </span><span class="s2">&quot;~/Sync/backing tracks/shows/2026-02-30 example.mp4&quot;</span></span></span>
</pre></figure><p>Finally, I use <a href="https://syncthing.net/">SyncThing</a> to automatically synchronize my <code>~/Sync</code> directory between my various computers, which is super handy. (It&rsquo;s also a <em>lot</em> easier than dealing with network shares!)</p><p>When it&rsquo;s time to perform, I&rsquo;ll use SteamVR&rsquo;s desktop overlay function to float my VLC window in the world with me, and so then I&rsquo;ll always have my visual reference where I need it. (So if you see me looking downward a lot, it isn&rsquo;t <em>just</em> me being introverted.)</p><p>When it comes to actually performing, I make sure that VLC has keyboard focus and then I can just press the space bar on my keyboard to start and, if necessary, pause the backing track.</p><h3 id="1302_h3_9_Doing-sound-checks">Doing sound checks<a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0#1302_h3_9_Doing-sound-checks" class="toc_link"></a></h3><p>Sound checks used to be rather difficult; previously, I&rsquo;d do a laborious process of recording the loopback interface into Audacity while performing parts of my set, listen back afterwards, and then try making incremental adjustments. This process was super annoying.</p><p>Nowadays I&rsquo;ve found a <a href="https://softwarerecs.stackexchange.com/questions/35552/record-a-sound-and-play-it-back-after-a-user-defined-delay">much better way</a>; basically:</p><p>First, I open two instances of VLC:</p>
<ul>
<li>The first instance gets my backing track (and continues to play to Playback 1+2)</li>
<li>The second instance is set to play to Playback 5+6, upon which I &ldquo;open capture device,&rdquo; set to the loopback audio with a 10-second caching delay.</li>
</ul>

<figure class="images"><a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0"><img src="https://sockpuppet.band/static/_img/c2/1dd6/vlc-delay-loop_3af4e3f6bf_530x580_q50.webp" width="530" height="580" srcset="https://sockpuppet.band/static/_img/c2/1dd6/vlc-delay-loop_3af4e3f6bf_530x580_q50.webp 1x, https://sockpuppet.band/static/_img/c2/1dd6/vlc-delay-loop_3af4e3f6bf_q50.webp 2x" loading="lazy" class="u-photo" alt="Setting up a delay loop in VLC"></a></figure>
<p>Then, I can unpause my backing track player and perform for 10 seconds, then pause the backing track while I listen to how it sounded. This gives me a much faster means of iterating on my adjustments and getting things sounding really good.</p>
            
                <hr/><ol><li id="d_e1302_fn1"><p>Props to <a href="https://nikofox.carrd.co/">Niko Fox</a> for turning me on to this specific wireless IEM unit.&nbsp;<a href="/blog/1302-VR-performance-setup-2.0#r_e1302_fn1" rev="footnote">↩</a></p></li><li id="d_e1302_fn2"><p>I actually have all four going to it but Playback 7+8 isn&rsquo;t used for anything. Someday I might figure out a way of using it for a click track or additional audio cues, though.&nbsp;<a href="/blog/1302-VR-performance-setup-2.0#r_e1302_fn2" rev="footnote">↩</a></p></li><li id="d_e1302_fn3"><p>I don&rsquo;t usually have the amplifier&rsquo;s speakers on when I&rsquo;m performing but it&rsquo;s nice to have when I&rsquo;m practicing. Additionally, the amplifier&rsquo;s line output and instrument input are no longer connected to anything, as they are not needed in this setup. I do still use the amplifier&rsquo;s power bus for my pedal board, however.&nbsp;<a href="/blog/1302-VR-performance-setup-2.0#r_e1302_fn3" rev="footnote">↩</a></p></li><li id="d_e1302_fn4"><p>Note that other people in the instance won&rsquo;t see the lips move, though, although for me it&rsquo;s most important that my local camera does. If you need the lip movement to be visible to someone else (for example, someone else recording/streaming you directly), set your microphone output level to 5%, which will broadcast your visemes to others while keeping the audio level as low as possible.&nbsp;<a href="/blog/1302-VR-performance-setup-2.0#r_e1302_fn4" rev="footnote">↩</a></p></li><li id="d_e1302_fn5"><p>Or I could try to remember to set my VRChat camera to &ldquo;audio from camera&rdquo; mode and pass the stereo through normally, but I usually forget to do this. It also makes communicating with others on stage much more difficult since consciously overriding the incorrect positional audio cues is super hard to brain.&nbsp;<a href="/blog/1302-VR-performance-setup-2.0#r_e1302_fn5" rev="footnote">↩</a></p></li><li id="d_e1302_fn6"><p>In theory one could use ASIO to mitigate the latency (via the <a href="https://github.com/Andersama/obs-asio">respective OBS plugin</a>), but there&rsquo;s still going to be <em>some</em> latency, and I err on the side of pragmatism since I&rsquo;m going to have to adjust things anyway. Also, even if the latency can be eliminated from OBS&rsquo;s point of view, it&rsquo;s still going to be present for VRChat, so it&rsquo;s going to need to be adjusted between the visuals and the audio, and that is, in my experience, much harder to do well.&nbsp;<a href="/blog/1302-VR-performance-setup-2.0#r_e1302_fn6" rev="footnote">↩</a></p><p>There&rsquo;s also the issue of ASIO often requiring exclusive access to the device, which means it might not even work in this situation to begin with.</p><p>So basically, ASIO <em>might</em> work but I haven&rsquo;t tried it nor have I seen any compelling reason to.</p></li><li id="d_e1302_fn7"><p>Although I&rsquo;m proud to say that most of the songs I perform I do have completely memorized, and the more I perform songs I&rsquo;m not off-book on yet, the closer I get to getting there. Assistive technology FTW.&nbsp;<a href="/blog/1302-VR-performance-setup-2.0#r_e1302_fn7" rev="footnote">↩</a></p></li></ol>
            

            

        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=VRChat">#VRChat</a>
        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=VR">#VR</a>
        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=performances">#Performances</a>
        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=hardware">#Hardware</a>
        

        ]]>



        </content>
        <category term="Blog" label="Blog" />
        
        
        <category term="VRChat" label="VRChat" />
        
        <category term="VR" label="VR" />
        
        <category term="Performances" label="performances" />
        
        <category term="Hardware" label="hardware" />
        

        

    </entry>
    <entry>
        
        <title>Lorenzo&#39;s Music Podcast</title>
        <link href="https://sockpuppet.band/blog/2251-Lorenzo-s-Music-Podcast" rel="alternate" type="text/html" />
        <published>2025-12-19T22:20:42-08:00</published>
        <updated>2025-12-19T22:20:42-08:00</updated>
        <id>urn:uuid:407e4bb5-d951-46f2-8343-ac5ec15693ba</id>
        <author><name>fluffy</name></author>
        <summary type="html"><![CDATA[<p>I was a guest over on <a href="https://www.lorenzosmusic.com/podcast/sockpuppet-lorenzos-music-podcast/">Lorenzo&rsquo;s Music Podcast</a>, where we talked about a bunch of topics including VR-based performances, creative self-expression, and the future of federated music streaming, among other things. Thank you so much to Tom Ray for having me on!</p>]]></summary>
        <content type="html"><![CDATA[

		

        



        <p>I was a guest over on <a href="https://www.lorenzosmusic.com/podcast/sockpuppet-lorenzos-music-podcast/">Lorenzo&rsquo;s Music Podcast</a>, where we talked about a bunch of topics including VR-based performances, creative self-expression, and the future of federated music streaming, among other things. Thank you so much to Tom Ray for having me on!</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/ljkWycR8tMY?si=MRuoGQ_jJmJiQx0c" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>


        
            
            

            

        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=podcast">#Podcast</a>
        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=guest+appearances">#GuestAppearances</a>
        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=discussion">#Discussion</a>
        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=VRChat">#VRChat</a>
        

        ]]>



        </content>
        <category term="Blog" label="Blog" />
        
        
        <category term="Podcast" label="podcast" />
        
        <category term="GuestAppearances" label="guest appearances" />
        
        <category term="Discussion" label="discussion" />
        
        <category term="VRChat" label="VRChat" />
        

        

    </entry>
    <entry>
        
        <title>Self-hosted streaming CDN</title>
        <link href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN" rel="alternate" type="text/html" />
        <published>2025-09-26T20:22:51-07:00</published>
        <updated>2025-09-26T20:22:51-07:00</updated>
        <id>urn:uuid:2a025873-f8cb-59b0-a816-98cf02912659</id>
        <author><name>fluffy</name></author>
        <summary type="html"><![CDATA[<p>Performers who do streaming-based performances on VRChat and other places have a few options for actually providing their stream. Once upon a time it was preetty common for people to use Twitch or YouTube Live, but those are now being locked down due to advertising considerations. So, many people currently use <a href="https://vrcdn.live/">VRCDN</a>, an inexpensive but limited hosted service that you have to pay monthly for. But for folks with a bit more technical acumen, there&rsquo;s another choice, <a href="https://owncast.online/">Owncast</a>, which is basically a self-hosted Twitch-like.</p>]]></summary>
        <content type="html"><![CDATA[

		

        



        <p>Performers who do streaming-based performances on VRChat and other places have a few options for actually providing their stream. Once upon a time it was preetty common for people to use Twitch or YouTube Live, but those are now being locked down due to advertising considerations. So, many people currently use <a href="https://vrcdn.live/">VRCDN</a>, an inexpensive but limited hosted service that you have to pay monthly for. But for folks with a bit more technical acumen, there&rsquo;s another choice, <a href="https://owncast.online/">Owncast</a>, which is basically a self-hosted Twitch-like.</p><p>Here&rsquo;s how I have mine set up and how I run it for (basically<sup id="r_e2089_fn1"><a href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#d_e2089_fn1" rel="footnote">1</a></sup>) free.</p>

        
            <h3 id="2089_h3_1_Local-server-origin">Local server (origin)<a href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#2089_h3_1_Local-server-origin" class="toc_link"></a></h3><p>First off, I have an Intel NUC running Linux<sup id="r_e2089_fn2"><a href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#d_e2089_fn2" rel="footnote">2</a></sup> on my home network. This computer runs a bunch of my home services but mostly sits idle. Its CPU is a 2.7GHz i7-8559U, which is sufficient to transcode my stream to a number of bitrates and resolutions simultaneously. I currently have the following bitrates configured:</p>
<ul>
<li>Original/raw stream (as configured in OBS; usually 1080p60 @ 6000 Kbps)</li>
<li>1080p60 @ 4500 Kbps</li>
<li>720p30 @ 2000 Kbps</li>
<li>360p24 @ 1000 Kbps</li>
<li>180p24 @ 500 Kbps</li>
</ul>
<p>In theory I should also be able to configure it to use Intel Quick Sync for a bit lower CPU utilization, although I haven&rsquo;t gone through the rigmarole to make that happen, as it hasn&rsquo;t been necessary.</p><p>Anyway, Owncast is running on its own user account, creatively called <code>owncast</code>. To make the server automatically start up, I have the following systemd unit file:</p><figure class="blockcode"><figcaption>/home/owncast/.config/system/user/owncast.service</figcaption><pre class="highlight" data-language="systemd" data-line-numbers><span class="line" id="e2089cb1L1"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L1"></a><span class="line-content"><span class="k">[Unit]</span></span></span>
<span class="line" id="e2089cb1L2"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L2"></a><span class="line-content"><span class="na">Description</span><span class="o">=</span><span class="s">Owncast Service</span></span></span>
<span class="line" id="e2089cb1L3"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L3"></a><span class="line-content"></span></span>
<span class="line" id="e2089cb1L4"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L4"></a><span class="line-content"><span class="k">[Service]</span></span></span>
<span class="line" id="e2089cb1L5"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L5"></a><span class="line-content"><span class="na">WorkingDirectory</span><span class="o">=</span><span class="s">/home/owncast/owncast</span></span></span>
<span class="line" id="e2089cb1L6"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L6"></a><span class="line-content"><span class="na">ExecStart</span><span class="o">=</span><span class="s">/home/owncast/owncast/owncast</span></span></span>
<span class="line" id="e2089cb1L7"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L7"></a><span class="line-content"><span class="na">Restart</span><span class="o">=</span><span class="s">always</span></span></span>
<span class="line" id="e2089cb1L8"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L8"></a><span class="line-content"><span class="na">RestartSec</span><span class="o">=</span><span class="s">5</span></span></span>
<span class="line" id="e2089cb1L9"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L9"></a><span class="line-content"></span></span>
<span class="line" id="e2089cb1L10"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L10"></a><span class="line-content"><span class="k">[Install]</span></span></span>
<span class="line" id="e2089cb1L11"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb1L11"></a><span class="line-content"><span class="na">WantedBy</span><span class="o">=</span><span class="s">default.target</span></span></span>
</pre></figure><p>To make this run, I had to enable lingering for the account, with <code>sudo loginctl enable-linger owncast</code> from an administrative user, and <code>systemctl --user enable owncast.service</code> from the owncast account.</p><h3 id="2089_h3_2_Proxy-server">Proxy server<a href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#2089_h3_2_Proxy-server" class="toc_link"></a></h3><p>The next thing to do was to expose this server to the greater Internet. There&rsquo;s a few ways you can go about doing this. The most straightforward, if you have an ISP that allows it, is to set up your home router to forward a particular port to the Owncast instance. However, many ISPs do not allow you to run servers this way, and even though mine does, I wasn&rsquo;t super comfortable with the idea of exposing a network port to the wider Internet or with having my home IP address be part of any public Internet service.</p><p>However, I already have a VPS with <a href="https://linode.com/">Akamai Cloud</a> which I use to run all of my websites. So, I set up an ssh tunnel (specifically using <a href="https://www.harding.motd.ca/autossh/">autossh</a> to automatically restart the connection if it drops). To that end, I made a second systemd unit:</p><figure class="blockcode"><figcaption>/home/owncast/.config/systemd/user/owncast-tunnel.service</figcaption><pre class="highlight" data-language="systemd" data-line-numbers><span class="line" id="e2089cb2L1"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L1"></a><span class="line-content"><span class="k">[Unit]</span></span></span>
<span class="line" id="e2089cb2L2"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L2"></a><span class="line-content"><span class="na">Description</span><span class="o">=</span><span class="s">Owncast ssh tunnel</span></span></span>
<span class="line" id="e2089cb2L3"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L3"></a><span class="line-content"></span></span>
<span class="line" id="e2089cb2L4"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L4"></a><span class="line-content"><span class="k">[Service]</span></span></span>
<span class="line" id="e2089cb2L5"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L5"></a><span class="line-content"><span class="na">ExecStart</span><span class="o">=</span><span class="s">autossh -NT -R 29929:localhost:8080 MYSERVER.example.com</span></span></span>
<span class="line" id="e2089cb2L6"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L6"></a><span class="line-content"><span class="na">Restart</span><span class="o">=</span><span class="s">always</span></span></span>
<span class="line" id="e2089cb2L7"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L7"></a><span class="line-content"><span class="na">RestartSec</span><span class="o">=</span><span class="s">5</span></span></span>
<span class="line" id="e2089cb2L8"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L8"></a><span class="line-content"></span></span>
<span class="line" id="e2089cb2L9"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L9"></a><span class="line-content"><span class="k">[Install]</span></span></span>
<span class="line" id="e2089cb2L10"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb2L10"></a><span class="line-content"><span class="na">WantedBy</span><span class="o">=</span><span class="s">default.target</span></span></span>
</pre></figure><p>where <code>MYSERVER.example.com</code> is the actual hostname of my VPS. I enabled this service with <code>systemctl --user enable owncast-tunnel.service</code> and now localhost connections to 29929 on my VPS connect to port 8080 on my NUC. (No need for Tailscale!)</p><p>Finally, I set up a caching reverse proxy for <a href="https://live.sockpuppet.band">my owncast server</a>. This is how I did it in nginx:</p><figure class="blockcode"><figcaption>/etc/nginx/vhosts-enabled/live.sockpuppet.band</figcaption><pre class="highlight" data-language="nginx" data-line-numbers><span class="line" id="e2089cb3L1"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L1"></a><span class="line-content"><span class="k">server</span><span class="w"> </span><span class="p">{</span></span></span>
<span class="line" id="e2089cb3L2"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L2"></a><span class="line-content"><span class="w">    </span><span class="kn">listen</span><span class="w"> </span><span class="mi">80</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L3"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L3"></a><span class="line-content"><span class="w">    </span><span class="kn">listen</span><span class="w"> </span><span class="s">[::]:80</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L4"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L4"></a><span class="line-content"><span class="w">    </span><span class="kn">server_name</span><span class="w"> </span><span class="s">live.sockpuppet.band</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L5"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L5"></a><span class="line-content"><span class="w">    </span><span class="kn">return</span><span class="w"> </span><span class="mi">301</span><span class="w"> </span><span class="s">https://</span><span class="nv">$host$request_uri</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L6"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L6"></a><span class="line-content"><span class="p">}</span></span></span>
<span class="line" id="e2089cb3L7"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L7"></a><span class="line-content"></span></span>
<span class="line" id="e2089cb3L8"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L8"></a><span class="line-content"><span class="k">proxy_cache_path</span><span class="w"> </span><span class="s">/var/tmp/live_sockpuppet</span><span class="w"> </span><span class="s">levels=1:2</span><span class="w"> </span><span class="s">keys_zone=live_sockpuppet:10m</span><span class="w"> </span><span class="s">max_size=10g</span></span></span>
<span class="line" id="e2089cb3L9"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L9"></a><span class="line-content"><span class="w">                 </span><span class="s">inactive=60m</span><span class="w"> </span><span class="s">use_temp_path=off</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L10"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L10"></a><span class="line-content"></span></span>
<span class="line" id="e2089cb3L11"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L11"></a><span class="line-content"><span class="k">server</span><span class="w"> </span><span class="p">{</span></span></span>
<span class="line" id="e2089cb3L12"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L12"></a><span class="line-content"><span class="w">    </span><span class="kn">server_name</span><span class="w"> </span><span class="s">live.sockpuppet.band</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L13"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L13"></a><span class="line-content"><span class="w">    </span><span class="kn">listen</span><span class="w"> </span><span class="mi">443</span><span class="w"> </span><span class="s">ssl</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L14"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L14"></a><span class="line-content"><span class="w">    </span><span class="kn">ssl_certificate</span><span class="w"> </span><span class="s">/path/to/sockpuppet.band.crt</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L15"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L15"></a><span class="line-content"><span class="w">    </span><span class="kn">ssl_certificate_key</span><span class="w"> </span><span class="s">/path/to/sockpuppet.band.key</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L16"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L16"></a><span class="line-content"></span></span>
<span class="line" id="e2089cb3L17"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L17"></a><span class="line-content"><span class="w">    </span><span class="kn">location</span><span class="w"> </span><span class="s">/</span><span class="w"> </span><span class="p">{</span></span></span>
<span class="line" id="e2089cb3L18"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L18"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">Host</span><span class="w"> </span><span class="nv">$host</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L19"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L19"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-Host</span><span class="w"> </span><span class="nv">$host</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L20"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L20"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-Server</span><span class="w"> </span><span class="nv">$host</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L21"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L21"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-Proto</span><span class="w"> </span><span class="nv">$scheme</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L22"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L22"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Real-IP</span><span class="w"> </span><span class="nv">$remote_addr</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L23"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L23"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-For</span><span class="w"> </span><span class="nv">$proxy_add_x_forwarded_for</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L24"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L24"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_http_version</span><span class="w"> </span><span class="mi">1</span><span class="s">.1</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L25"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L25"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">Upgrade</span><span class="w"> </span><span class="nv">$http_upgrade</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L26"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L26"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">Connection</span><span class="w"> </span><span class="nv">$connection_upgrade</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L27"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L27"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_pass</span><span class="w"> </span><span class="s">http://127.0.0.1:29929</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L28"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L28"></a><span class="line-content"><span class="w">        </span><span class="kn">proxy_cache</span><span class="w"> </span><span class="s">live_sockpuppet</span><span class="p">;</span></span></span>
<span class="line" id="e2089cb3L29"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L29"></a><span class="line-content"><span class="w">    </span><span class="p">}</span></span></span>
<span class="line" id="e2089cb3L30"><a class="line-number" href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#e2089cb3L30"></a><span class="line-content"><span class="p">}</span></span></span>
</pre></figure><p>This caching configuration means that this edge server only needs to proxy each HLS segment from my home network once, so in theory I can get a full gigabit of upstream from my VPS without overly burdening my home connection (although my home connection has plenty of bandwidth to spare, all the same).</p><h3 id="2089_h3_3_Wider-distribution-with-a-CDN">Wider distribution with a CDN<a href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#2089_h3_3_Wider-distribution-with-a-CDN" class="toc_link"></a></h3><p>This is optional, but I also use <a href="https://cloudflare.com/">Cloudflare CDN</a> for DDOS and bot mitigation, as well as better caching performance worldwide. So far I&rsquo;ve never come even <em>remotely</em> close to exceeding the bandwidth capacity of my VPS (which should theoretically be able to serve around 200 simultaneous viewers), but Cloudflare&rsquo;s free tier means I don&rsquo;t have to worry about scaling at all.</p><p>I&rsquo;m not a huge fan of Cloudflare for a number of reasons, but it&rsquo;s made it a lot easier for me to deal with the constant deluge of AI bot traffic that&rsquo;s been causing me so much stress lately, and having a proper geographically-distributed CDN is a nice bonus.</p><p>In theory, if your ISP allows running servers, you could also configure Cloudflare to talk directly to your home router, although I believe doing arbitrary port forwards requires a paid plan.</p><h3 id="2089_h3_4_Finally-streaming">Finally, streaming!<a href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#2089_h3_4_Finally-streaming" class="toc_link"></a></h3><p>To send a stream out, instead of using the public-facing hostname (live.sockpuppet.band), I connect OBS to the local IP address, so that I don&rsquo;t have to go out to the public Internet just to be routed back home. This way I also don&rsquo;t have to expose Owncast&rsquo;s RTMP port to the public Internet, which gives me better security. On the minus side, this means I cannot easily share my server with others to allow others to stream with my infrastructure, but that&rsquo;s never come up. If I ever wanted to do a cooperative stream with someone, I could use a WebRTC proxy such as <a href="https://vdo.ninja/">VDO.ninja</a>, but setting that up is outside the scope of this blog post.</p><p>Anyway, when someone connects to <a href="https://live.sockpuppet.band">my owncast</a> they are viewing it through Cloudflare, which pulls the data from my VPS, which in turn proxies it over the SSH tunnel to the Owncast instance running on my device at home. The raw stream (used, for example, by a VRChat in-world player) is available at <code>https://live.sockpuppet.band/hls/stream.m3u8</code>.</p><h3 id="2089_h3_5_How-to-roll-your-own-streaming-C">How to roll your own streaming CDN<a href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN#2089_h3_5_How-to-roll-your-own-streaming-C" class="toc_link"></a></h3><p>Okay so let&rsquo;s say you just want to roll your own VRCDN-like thing, and don&rsquo;t care about having your streaming box be directly on your local network. Here&rsquo;s what I&rsquo;d do for that:</p>
<ol>
<li>Set up a VPS of some sort, even one which only runs when you need it to (which both DigitalOcean and Linode/Akamai support)</li>
<li>Install <a href="https://owncast.online/">owncast</a> on it</li>
<li>Install nginx or apache as a fronting webserver, and have it just reverse proxy into Owncast (so you can run Owncast on port 80/443 without having to run Owncast itself as root)</li>
<li>Front the server with Cloudflare, and have it cache aggressively</li>
</ol>
<p>For streaming you&rsquo;ll need to connect directly to the server by IP address (or by having a hostname that&rsquo;s <em>not</em> Cloudflare-proxied), but otherwise you&rsquo;re good to go from here.</p><p>In such a setup you&rsquo;ll probably need to limit the bitrates that you provide.</p><p>Anyway, a suitably-capable VPS will cost around 5.4¢/hour while it&rsquo;s running, and theoretically be able to support hundreds, if not thousands, of simultaneous viewers.</p>
            
                <hr/><ol><li id="d_e2089_fn1"><p>It&rsquo;s only basically free because I already have a public Internet server I run my websites on and a local computer I can use for Owncast. If you don&rsquo;t already have a VPS of some sort, my particular setup won&rsquo;t work for you.&nbsp;<a href="/blog/2089-Self-hosted-streaming-CDN#r_e2089_fn1" rev="footnote">↩</a></p></li><li id="d_e2089_fn2"><p>All of this could also be run on Windows or macOS, but setting up a persistent server and ssh tunnel on those platforms is not something I&rsquo;ve had to internalize.&nbsp;<a href="/blog/2089-Self-hosted-streaming-CDN#r_e2089_fn2" rev="footnote">↩</a></p></li></ol>
            

            

        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=technology">#Technology</a>
        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=owncast">#Owncast</a>
        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=streaming">#Streaming</a>
        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=VRChat">#VRChat</a>
        

        ]]>



        </content>
        <category term="Blog" label="Blog" />
        
        
        <category term="Technology" label="technology" />
        
        <category term="Owncast" label="owncast" />
        
        <category term="Streaming" label="streaming" />
        
        <category term="VRChat" label="VRChat" />
        

        

    </entry>
    <entry>
        
        <title>VR performance stuff</title>
        <link href="https://sockpuppet.band/blog/3183-VR-performance-stuff" rel="alternate" type="text/html" />
        <published>2025-09-07T22:06:39-07:00</published>
        <updated>2026-01-24T09:01:40+00:00</updated>
        <id>urn:uuid:373513c2-f1fc-5791-9113-b1a3e01da404</id>
        <author><name>fluffy</name></author>
        <summary type="html"><![CDATA[<p>Today was the second day of VRelium Enchanted, which <a href="https://sockpuppet.band/live/3348-VRelium-Enchanted-2025">I performed at</a> and had a really good time. I&rsquo;m going to talk a bit about how VRChat performances work and some thoughts about my most recent one, in particular.</p>]]></summary>
        <content type="html"><![CDATA[

		

        



        <p>Today was the second day of VRelium Enchanted, which <a href="https://sockpuppet.band/live/3348-VRelium-Enchanted-2025">I performed at</a> and had a really good time. I&rsquo;m going to talk a bit about how VRChat performances work and some thoughts about my most recent one, in particular.</p><p><mark>UPDATE:</mark> This is obsolete! It might still be useful for some folks (especially those working on a budget or trying to get ideas of how to cobble someting together), but <a href="https://sockpuppet.band/blog/1302-VR-performance-setup-2.0">my current setup</a> is completely different and much easier to work with.</p>

        
            <h3 id="3183_h3_1_VR-venues">VR venues<a href="https://sockpuppet.band/blog/3183-VR-performance-stuff#3183_h3_1_VR-venues" class="toc_link"></a></h3><p>Performing live music in VR has a very different set of considerations than from real life. It&rsquo;s very difficult to get an ensemble together due to lag between people<sup id="r_e3183_fn1"><a href="https://sockpuppet.band/blog/3183-VR-performance-stuff#d_e3183_fn1" rel="footnote">1</a></sup>, and also the way that audio is usually sent to the world adds even more lag and makes it impossible for two performers to both share audio into the world.</p><p>There are two major styles of performance space: mic boosted, and streamed. Some worlds, such as <a href="https://vrchat.com/home/world/wrld_31ff6bb7-b2f5-4d2a-aa38-1dc93926bb53/info">Transitions Club</a> (which I&rsquo;ve used for most of my solo shows, such as the recent <a href="https://sockpuppet.band/live/2083-RFFF-25-show">Radio Free Fedi Fest</a>) support both modes of operation, but most I&rsquo;ve encountered only support streaming.</p><h4 id="3183_h4_2_Mic-boosting">Mic boosting<a href="https://sockpuppet.band/blog/3183-VR-performance-stuff#3183_h4_2_Mic-boosting" class="toc_link"></a></h4><p>Mic boosting is typically used by open mics or other situations where a lot of performers are playing just one or two songs; for example, <a href="https://transacademy.org/">Trans Academy</a> does this for the short Moonlit performances (but not for DJ sets or full concerts), and most open mics do this as well. The setup is pretty simple and easy; from the performer&rsquo;s point of view<sup id="r_e3183_fn2"><a href="https://sockpuppet.band/blog/3183-VR-performance-stuff#d_e3183_fn2" rel="footnote">2</a></sup>, there&rsquo;s a special region in the world which amplifies the volume and/or decreases the attenuation of anyone standing in it, so anything they say over their microphone gets put in everyone&rsquo;s ears.</p><p>This has a number of advantages:</p>
<ul>
<li>It&rsquo;s super easy for people to set up since there&rsquo;s plenty of ways of getting arbitrary audio fed into the VRChat microphone input</li>
<li>The performer can also simultaneously stream to the outside world including audience noise/reactions</li>
<li>Interactions with the audience are more or less immediate</li>
<li>A show can be put on by a single person with no support team</li>
</ul>
<p>But it has some pretty hefty limitations:</p>
<ul>
<li>People in the audience generally can&rsquo;t change the volume level of the performance</li>
<li><del>VRChat&rsquo;s own audio transport is pretty low-quality and is meant for real-time speech, not for music (for example, <a href="https://sockpuppet.band/live/2011-Moonlit-EU">this is what it sounds like on my performance in-world</a>, compared to the quality of <a href="https://sockpuppet.band/live/613-Moonlit-Academy-I-LOVE-YOU">my local signal</a>, and the more complex the music, the worse it gets)</del> <mark>UPDATE:</mark> This has actually changed; as of December 2025 they&rsquo;ve vastly improved the mic audio, by switching to <a href="https://docs.vrchat.com/docs/vrchat-202542">Steam Audio</a>.</li>
<li>You can <em>only</em> get audio through, rather than any extra visuals</li>
<li>Doing more complex things with the audio gets incredibly finicky and error-prone</li>
<li>The audience size is limited to however many can fit in a single world instance</li>
</ul>
<h4 id="3183_h4_3_Streaming">Streaming<a href="https://sockpuppet.band/blog/3183-VR-performance-stuff#3183_h4_3_Streaming" class="toc_link"></a></h4><p>A streaming approach is much more commonly used for music festivals such as Furality, VRelium, CMFS, and so on. In this setup, the performer is sending their audio and visuals through streaming software (typically <a href="https://obsproject.com/">OBS</a>) to a streaming provider. <a href="https://vrcdn.live/">VRCDN</a> is very popular but any number of things work, including <del>Twitch, YouTube Live, and</del> <a href="https://owncast.online/">owncast</a>, the last of which being <a href="https://sockpuppet.band/blog/2089-Self-hosted-streaming-CDN">what I use for my independent shows</a><sup id="r_e3183_fn3"><a href="https://sockpuppet.band/blog/3183-VR-performance-stuff#d_e3183_fn3" rel="footnote">3</a></sup>.</p><p>Streaming has a bunch of advantages over mic boosting:</p>
<ul>
<li>The audio quality is way better</li>
<li>There&rsquo;s much better control over the audio signal, and in particular since VRChat always uses its view of the mic input as the lipsync source, being able to separate your vocal audio from your other instruments makes for a cleaner performance</li>
<li>The performer can provide visuals that will appear in the world in some way, usually on a large projection screen behind the stage, and some worlds are built to support multi-screen visuals (by mapping different parts of the screen image to different surfaces in the world)</li>
<li>The audience can be <em>way</em> larger since multiple instances can reference the same video stream (and some venues can also do holographic projection of performers between instances, which is also done using clever video and shader tricks)</li>
<li>You also automatically have a stream that can be viewed from outside VRChat or recorded for later editing</li>
<li>Various compositing proxies can be used to add even more visuals to the outside world stream/recording (for example, having multiple camera operators streaming to video sources that are then assembled by someone else); for example it&rsquo;s common for music festivals to map the performer&rsquo;s visuals to one screen while providing audio visualizations for the audience and a countdown timer for the preformer</li>
</ul>
<p>But it also has disadvantages:</p>
<ul>
<li>You generally need a support team managing the stream (it&rsquo;s not super feasible for solo shows &mdash; it&rsquo;s <em>possible</em> and I&rsquo;ve done it, but it&rsquo;s much more of a hassle)</li>
<li>There&rsquo;s a <em>lot</em> of lag between the world and the stream (usually on the order of 5-15 seconds), so interactions with the audience are confusing or on a delay, and people who are looking directly at the performer (rather than the screen) will have extremely bad lip sync<sup id="r_e3183_fn4"><a href="https://sockpuppet.band/blog/3183-VR-performance-stuff#d_e3183_fn4" rel="footnote">4</a></sup></li>
<li>Because the performer is streaming audio and video to the world, extra considerations are necessary for a livestream that includes audience reactions</li>
<li><del>If the venue is small and doesn&rsquo;t have a means of <em>muting</em> on-stage performers, the audience may hear doubled audio with considerable delay between them</del> <mark>UPDATE:</mark> Along with the improvements to mic audio, VRChat now allows you to set your microphone output level to 0% which has the effect of preserving lip sync without broadcasting any audio into the instance.</li>
</ul>
<p>Due to these disadvantages, and since my solo shows tend to be pretty small, if I&rsquo;m going solo it&rsquo;s usually using a mic boost.</p><h3 id="3183_h3_4_A-typical-setup">A typical setup<a href="https://sockpuppet.band/blog/3183-VR-performance-stuff#3183_h3_4_A-typical-setup" class="toc_link"></a></h3><p>Most people who perform in VR are exclusively using backing tracks (often ones obtained from karaoke videos, if they&rsquo;re doing covers of songs), and use <a href="https://vb-audio.com/Voicemeeter/">Voicemeeter</a>, a virtual mixer combines multiple audio inputs into a single virtual audio source.</p><p>For a mic-boosted performance, they&rsquo;ll be using Voicemeeter to combine the backing track with their microphone, and also monitor the audio back to their own ears.</p><p>They may also be doing it that way for a streamed performance, although for streaming the better option is to use OBS&rsquo;s audio mixing and monitoring for the backing track.</p><h3 id="3183_h3_5_My-typical-setup">My typical setup<a href="https://sockpuppet.band/blog/3183-VR-performance-stuff#3183_h3_5_My-typical-setup" class="toc_link"></a></h3><p>Because I am <del>a masochist</del> coming from the tradition of conventional live performances, I have a tendency to want to perform as much live as possible, and have previously never used a backing track<sup id="r_e3183_fn5"><a href="https://sockpuppet.band/blog/3183-VR-performance-stuff#d_e3183_fn5" rel="footnote">5</a></sup>.</p><p>Typically I have Voicemeeter capturing my vocal microphone (which is usually the mic built-in to my <a href="https://www.bigscreenvr.com/">Bigscreen Beyond</a>) and my computer&rsquo;s onboard line input, which I then have various amps/pedals/mixers connected to for my performance instruments; my typical loadout is:</p>
<ul>
<li>My guitar</li>
<li>A cheap reverb pedal from AliExpress</li>
<li>A cheap distortion pedal, also from AliExpress</li>
<li>A Boss RC-20 looper pedal</li>
<li>A dynamic mic, for percussion and such going through the looper</li>
<li>A small <a href="https://www.musiciansfriend.com/amplifiers-effects/zt-lunchbox-junior-guitar-combo-amp/h82899000001000">lunchbox amplifier</a>, which is a simple way of amplifying that mess to line-level and giving me basic monitoring</li>
</ul>
<p>I then also have VRChat&rsquo;s voice input set to Voicemeeter.</p><p>When I&rsquo;m performing, regardless of whether it&rsquo;s mic-boost or streamed, I have a bunch of OBS scenes with different setups for different purposes, but generally-speaking my scene setup is:</p>
<ul>
<li>A <a href="https://github.com/Off-World-Live/obs-spout2-plugin">Spout2 capture source</a> (which allows OBS to directly project VRChat&rsquo;s camera capture rather than having to make a round trip through the display compositor)</li>
<li>Audio sources for Voicemeeter and then direct inputs for my headset mic, the computer line input, and a music player source for backing tracks</li>
<li>Also an audio output capture for my headset speakers (to capture in-game audio)</li>
<li>Whatever visuals I want to overlay on the stream (<a href="https://github.com/phandasm/waveform">Waveform</a> is especially useful)</li>
</ul>
<p>I make heavy use of OBS&rsquo;s multichannel audio functionality for this. I set channel 1 to be whatever I want to go to the stream. What goes on here depends on the kind of performance I&rsquo;m doing:</p>
<ul>
<li>If I&rsquo;m doing a mic boosted performance, it&rsquo;ll typically be my performance audio (either Voicemeeter, or a mix of mic+line input) mixed with the in-game audio so the livestream audience can hear the in-game audience as well</li>
<li>If I&rsquo;m doing a streamed performance, it&rsquo;ll be just my performance audio as a mix (usually the raw inputs, <em>not</em> Voicemeeter, as Voicemeeter adds a bit of lag making the timing of the backing track to be somewhat off)</li>
</ul>
<p>Regardless of this, I also record each separate thing to separate audio channels:</p>
<ul>
<li>Channel 2: vocal mic</li>
<li>Channel 3: line input</li>
<li>Channel 4: backing track</li>
<li>Channel 5: game audio</li>
<li>Channel 6: Voicemeeter</li>
</ul>
<p>I rarely actually use the Voicemeeter channel anymore (since I switched to directly mixing the live inputs to the stream) but I&rsquo;d might as well keep it around, just in case (although keep in mind that using it will require latency compensation). There&rsquo;s been a few times that it&rsquo;s been helpful due to OBS settings getting messed up, for example, so I actually didn&rsquo;t end up recording my raw instrument channel, for example.</p><p>Depending on whether I&rsquo;m using Voicemeeter or my raw microphone as my vocal input affects what sort of lipsync issues I have in the stream and/or recorded video. So I try to keep them the same as each other, but it&rsquo;s easy to forget and not a <em>huge</em> deal to fix since it&rsquo;s usually only offset by 1-2 frames (and VRChat&rsquo;s lip sync isn&rsquo;t all that great anyway).</p><h3 id="3183_h3_6_My-usual-performances">My usual performances<a href="https://sockpuppet.band/blog/3183-VR-performance-stuff#3183_h3_6_My-usual-performances" class="toc_link"></a></h3><p>So, when I perform, I&rsquo;m typically playing guitar or piano and singing, and occasionally making use of my effect pedals (especially the looper). Because I need to be able to see my guitar&rsquo;s fretboard and/or piano&rsquo;s keys while I perform, I built a custom headset gasket (based on the <a href="https://www.printables.com/model/751989-slimterface-flipterface-customface-for-bigscreen-b">Slimterface</a>, modified with a big cutout on the bottom, which I really should get around to uploading the files for at some point, oh <a href="https://www.printables.com/model/1408641-slimterface-modded-for-musical-performances">here we go</a>).</p><p>I still haven&rsquo;t figured out a good way of tracking my hand movements while playing guitar in-headset. I&rsquo;ve tried <a href="https://beesbuzz.biz/blog/7168-On-the-quest-for-VR-hand-tracking">a bunch of things</a> and so far the best results I&rsquo;ve gotten have been with a <a href="https://www.ultraleap.com/">Leapmotion 1</a> and <a href="https://github.com/Nyabsi/driver_leapify/">Leapify</a>, but it&rsquo;s still been pretty inconsistent and fiddly (but I have a few more things to try before I give up entirely). But for now, when I&rsquo;m playing guitar, I just signify it by swapping to a version of my avatar that&rsquo;s wearing a guitar and then people can just see my arms hang limply by my sides.</p><p>Also, because VRChat doesn&rsquo;t really have any way of bringing printouts into the world with you, to keep my setlist at the ready I open it up in a text editor or similar (usually synced with iCloud Notes or <a href="https://syncthing.net/">SyncThing</a> or whatever) and then attach the window to my VR playspace from the SteamVR overlay. This can be a little confusing, since it blocks a large part of my field of view and audience members can&rsquo;t tell that they&rsquo;re behind it (since it only exists locally and not in VRChat itself).</p><p>Since I have VRC+ I could also theoretically make an image of my setlist and print it into the world, but that makes it a manipulable object that people in the audience could steal and mess with, so I haven&rsquo;t ever actually done that (also music festivals tend to disable or force-remove prints for performance reasons).</p><p>There&rsquo;s probably some clever thing I could do with OSC to provide myself a local avatar HUD or something, but the SteamVR overlay works well enough for me.</p><h3 id="3183_h3_7_What-I-did-tonight">What I did tonight<a href="https://sockpuppet.band/blog/3183-VR-performance-stuff#3183_h3_7_What-I-did-tonight" class="toc_link"></a></h3><p>I have a chronic pain disorder which flares up sometimes. On the days leading up to this weekend it was flaring up pretty badly, so I figured I&rsquo;d play it safe and use backing tracks for once. Since all my music is original, I bounced out vocal-free versions of the songs I was going to perform, then combined them into a single file with a suitable gap between each song. I did leave some time at the end for an acoustic performance of <a href="https://sockpuppet.band/track/strategies-to-live">Strategies to Live</a>, because I&rsquo;m not at all happy with the quality of the album recording, and I also wanted a bit more flexibility in how I performed it.</p><p>It turned out that my pain flareup had subsided by performance time, but I decided to go with the backing track anyway, as a bit of an experiment.</p><p>My overarching philosophy is that the live version of a song should be special, and a reinterpretation of the album version. Using the album recording as a backing track flies in the face of that. However, this only really makes sense in a context where the audience already knows my music; generally when I&rsquo;m performing at a larger show, most of the audience is not familiar with my music, and as a result doesn&rsquo;t actually know that there&rsquo;s anything special about an acoustic guitar-folk performance of a <a href="https://sockpuppet.band/track/freak-flag">sex-positive hip-hop song</a> or a <a href="https://sockpuppet.band/track/behind-a-mask">90s alt-rock song</a> or a <a href="https://sockpuppet.band/track/material-change">hardstyle dancepop track</a>.</p><p>Further, genre bias is a thing, and when people get the impression that all of my music is acoustic indie rock, if they aren&rsquo;t into acoustic indie rock they have no reason to check my music out to hear how it really is.</p><p>So, at least for this large show I decided it&rsquo;d be interesting to see how the audience reacts to the songs as they originally were, rather than the &ldquo;special&rdquo; renditions I do as a treat. And judging by the audience reaction, it went over pretty well! It was also nice having my hands free, so I could actually move around and dance as I performed, and also could do appropriate avatar switches during some songs (particularly demonstrating some of the titular material changes in Material Change).</p><p>But I also ended up realizing that for my live performances, I put a <em>lot</em> of muscle memory into things, and there were a few spots where I came close to forgetting how the words went because I needed the shape of the chords I was making to cue me on them.</p><p>A baked backing track had another nice bonus in that I didn&rsquo;t need to display my setlist, because I could just use audio cues to know which song I was performing. But on the downside, some of the intra-song timings weren&rsquo;t quite right. I have a particular transition I like to do from <a href="https://sockpuppet.band/track/youre-never-around">You&rsquo;re Never Around</a> to <a href="https://sockpuppet.band/track/better-than-before">Better Than Before</a> and while I worked embarrassingly-long on trying to nail the timing in my backing track, I still feel like it didn&rsquo;t line up with how I wanted it to. It&rsquo;s probably a thing that only I would ever notice, though.</p><p>This also meant I was basically on-rails with no ability to adjust timing based on mood or tripping up on things or whatever. This was, ultimately, more good than bad, since it meant my set length was timed out perfectly (aside from Strategies to Live, which I was able to perform a bit faster than usual to make up for some previous schedule slippage), and also it kept me from rushing my songs, which in turn made tripping up much less likely.</p><p>In most of my festival sets I&rsquo;ve ended up doing one big flub and just powering through it, and tonight I only did a couple of minor flubs which nobody but me would have noticed anyway (even if they were super familiar with my songs which, let&rsquo;s face it, nobody else is).</p><p>I also loved being able to be way more expressive. My avatar is set up to allow me to puppet the eye and mouth shapes through hand gestures, which is pretty common, and I designed my puppetry setup specifically around doing karaoke, which this was just sort of an ascended version of anyway. Having the ability to make hand gestures at all is a huge improvement.</p><p>(That said, what&rsquo;d be even better is getting proper eye and mouth tracking support so I don&rsquo;t have to do puppetry to begin with, but I&rsquo;m not ready to spend that kind of money right now.)</p><p>Even without the puppetry aspect, I also had friends and fans arrive in the audience and would wave at me, and I was able to wave back, which made a couple of them absolutely delighted!</p><p>So, yeah, it gave me a much better audience connection, much better expressiveness in general, a much less stressful performance experience, and me just plain sounding better.</p><p>But in doing so I also gave up an amount of spontaneity, and also a feeling that I was actually <em>performing</em> and not just doing, y&#39;know, karaoke. Which just feels weird to me. It feels like I&rsquo;m lowering my standards, but the audience doesn&rsquo;t care at all, and if anything the audience seems to prefer the &ldquo;karaoke&rdquo; form.</p><h3 id="3183_h3_8_Future-plans">Future plans<a href="https://sockpuppet.band/blog/3183-VR-performance-stuff#3183_h3_8_Future-plans" class="toc_link"></a></h3><p>I think I&rsquo;ll go with something like this:</p>
<ul>
<li>For small shows (like Moonlit) and solo shows (where my existing fans will be the majority of the audience) I&rsquo;ll continue doing things mostly live on instruments, although I&rsquo;ll probably start to incorporate more backing tracks in as well to expand my repertoire, since many of my songs aren&rsquo;t super feasible to have a guitar rendition of (I&rsquo;d love to be able to do a live version of <a href="https://sockpuppet.band/track/a-long-plastic-hallway">A Long Plastic Hallway</a>, for example)</li>
<li>For larger shows I&rsquo;ll continue to do a mix of studio-version backing tracks and acoustic versions as appropriate</li>
<li>For <em>major</em> shows (like if I ever get accepted into Furality) I&rsquo;ll possibly make some custom backing tracks just for the show</li>
</ul>
<p>Also, I can still be proud that I&rsquo;m using my own backing tracks for my own songs. Not that there&rsquo;s anything wrong with people using existing karaoke versions for their covers, and obviously audiences don&rsquo;t mind it at all (and are just there to hear amazing singers singing songs they like). And who knows, if I keep uploading <a href="https://www.youtube.com/playlist?list=PLNRLpYEdwBNipgKir3qPtIf3AEm7B3Fnk">karaoke tracks</a>, maybe someday I&rsquo;ll hear someone doing a cover of one of my songs at one of these things.</p>
            
                <hr/><ol><li id="d_e3183_fn1"><p>You <em>can</em> do limited ensembles by having a chain of people streaming to one another, as long as nobody earlier in the chain needs to be able to hear anyone later in the chain, but that can also be difficult to manage and coordinate. Plus, every link in the chain is an opportunity for network problems.&nbsp;<a href="/blog/3183-VR-performance-stuff#r_e3183_fn1" rev="footnote">↩</a></p><p>Or you can just have everyone be physically in the same room.</p></li><li id="d_e3183_fn2"><p>The actual implementation of this is much more complicated but that&rsquo;s outside the scope of this article.&nbsp;<a href="/blog/3183-VR-performance-stuff#r_e3183_fn2" rev="footnote">↩</a></p></li><li id="d_e3183_fn3"><p>Unfortunately Twitch and YouTube are no longer viable options, as their respective wars on adblockers have prevented third-party streaming clients from reliably accessing the streams anymore, and that includes VRChat. The death of open standards is an awful thing to witness in real time.&nbsp;<a href="/blog/3183-VR-performance-stuff#r_e3183_fn3" rev="footnote">↩</a></p></li><li id="d_e3183_fn4"><p>Many performers opt to just mute their in-game mic so that there&rsquo;s no lip sync at all, which is throwing out the baby with the bath water, IMO.&nbsp;<a href="/blog/3183-VR-performance-stuff#r_e3183_fn4" rev="footnote">↩</a></p></li><li id="d_e3183_fn5"><p>Except when doing karaoke, of course.&nbsp;<a href="/blog/3183-VR-performance-stuff#r_e3183_fn5" rev="footnote">↩</a></p></li></ol>
            

            

        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=VRChat">#VRChat</a>
        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=VR">#VR</a>
        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=performances">#Performances</a>
        

        ]]>



        </content>
        <category term="Blog" label="Blog" />
        
        
        <category term="VRChat" label="VRChat" />
        
        <category term="VR" label="VR" />
        
        <category term="Performances" label="performances" />
        

        

    </entry>
    <entry>
        
        <title>Furality is gonna be amazing!</title>
        <link href="https://sockpuppet.band/blog/3123-Furality-is-gonna-be-amazing" rel="alternate" type="text/html" />
        <published>2025-05-22T09:36:08-07:00</published>
        <updated>2025-05-22T09:36:08-07:00</updated>
        <id>urn:uuid:74048d8f-7c42-5a07-8888-8949228b202f</id>
        <author><name>fluffy</name></author>
        <summary type="html"><![CDATA[<p><a href="https://furality.org/">Furality</a> is an annual virtual furry conference that takes place entirely in <a href="https://vrchat.com">VRChat</a>. I have a dealer&rsquo;s den booth this year, booth 816 (second level of the 2D Art + Miscellaneous) section, and I&rsquo;m super excited!</p>]]></summary>
        <content type="html"><![CDATA[

		

        



        <p><a href="https://furality.org/">Furality</a> is an annual virtual furry conference that takes place entirely in <a href="https://vrchat.com">VRChat</a>. I have a dealer&rsquo;s den booth this year, booth 816 (second level of the 2D Art + Miscellaneous) section, and I&rsquo;m super excited!</p><p>Last night Furality opened up a dealer&rsquo;s den preview so that we could check that our booths are set up correctly, and as a treat we got to see a decent chunk of the world and the overall style of the show, and I gotta say, it&rsquo;s <em>incredible</em>. The Furality team have knocked it out of the park this year, and have really outdone themselves. From what I&rsquo;ve seen this isn&rsquo;t just going to be an incredible con, it&rsquo;s going to be an amazing VRChat experience, and I am absolutely thrilled to be a part of it.</p><p>If you&rsquo;re at all in VRChat (even if you aren&rsquo;t at all interested in furry stuff), or heck, even if you&rsquo;ve been thinking of trying VRChat out, I highly recommend coming to Furality Somna so that you can experience the joy. Also, you don&rsquo;t need a VR setup to use VRChat! it just helps with the immersion (although just a warning, if you play it on desktop or cellphone you&rsquo;ll probably end up really wanting to get a headset anyway).</p><p>Also, I plan on doing various impromptu shows at various places throughout the con, and if you see me wandering around, feel free to come up and say &ldquo;hi!&rdquo;</p>

        
            
            

            

        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=Furality">#Furality</a>
        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=furry">#Furry</a>
        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=VRChat">#VRChat</a>
        

        ]]>



        </content>
        <category term="Blog" label="Blog" />
        
        
        <category term="Furality" label="Furality" />
        
        <category term="Furry" label="furry" />
        
        <category term="VRChat" label="VRChat" />
        

        

    </entry>
    <entry>
        
        <title>Concert time polling</title>
        <link href="https://sockpuppet.band/blog/1990-Concert-time-polling" rel="alternate" type="text/html" />
        <published>2024-12-18T19:25:37-08:00</published>
        <updated>2024-12-18T19:25:37-08:00</updated>
        <id>urn:uuid:bf17a9d0-b9c1-5ae2-930c-00ae7b576799</id>
        <author><name>fluffy</name></author>
        <summary type="html"><![CDATA[<p>Hey y&#39;all, I&rsquo;m trying to figure out when I should schedule my next VRChat concert for. If you&rsquo;d be so kind, please head over to <a href="https://whenisgood.net/qdgrgec">this poll</a> and click on the times which work well for you. (Remember to set your timezone as well!)</p>]]></summary>
        <content type="html"><![CDATA[

		

        



        <p>Hey y&#39;all, I&rsquo;m trying to figure out when I should schedule my next VRChat concert for. If you&rsquo;d be so kind, please head over to <a href="https://whenisgood.net/qdgrgec">this poll</a> and click on the times which work well for you. (Remember to set your timezone as well!)</p><p>Thanks!</p>

        
            
            

            

        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=VRChat">#VRChat</a>
        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=concerts">#Concerts</a>
        
        <a rel="tag" href="https://sockpuppet.band/blog/?tag=scheduling">#Scheduling</a>
        

        ]]>



        </content>
        <category term="Blog" label="Blog" />
        
        
        <category term="VRChat" label="VRChat" />
        
        <category term="Concerts" label="concerts" />
        
        <category term="Scheduling" label="scheduling" />
        

        

    </entry>
    

    
</feed>