Two-Fisted Tales of House Music's Own Sysadmin

Well, I think I got things working. Many Bothans died to bring us this information. To recap, goals include:

  • Stream audio to icecast, from either line-in or from the desktop audio output;
  • Acquire that same audio in OBS, to stream to RTMP;
  • Switch the audio input that we're reading from under cron control.

Every single layer of software involved in this process conspires to make this as difficult as possible, especially the automation.

Things that don't work:

  • Nicecast, which is no longer supported on macOS 10.15.
  • ffmpeg, which can't read audio from AVFoundation devices without glitching. There are five year old patches that might have fixed this that never landed and no longer apply.
  • DarkIce, which claims to support CoreAudio but does not (also the author is a dick).
  • JackAudio, which does not work on macOS 10.15.
  • Streaming to icecast from OBS, because you can't stream to two destinations at the same time without giving up the ability to also archive video to disk.

Here's how I made it go:

  • For audio input to the video stream: OBS doesn't support even the most remedial scripting, through AppleScript or otherwise, but it does let you assign a hot-key to a "scene". So make a different scene for each audio input, assign a function key to it, and use osascript to type those function keys at OBS at the appropriate time. Pepper your scripts with "sleep" statements until things mostly work, mostly.

  • To record from the system audio in OBS, I had been using iShowU, because OBS didn't seem to support anything else that works on 10.15. And by "iShowU" I mean "iShowUAudioCapture", not "iShowU Instant" or "iShowU Studio", which are separate paid products. But, see below...

  • For audio input to the icecast stream: Audio Hijack supports the devices well, but also has not even the most remedial automation support. And doesn't have the "scene hotkey" thing that OBS does, though it does let you type Cmd-R to play/pause. But, I found a kludge:

    1. Launch Audio Hijack. Set it up for Line In → Icecast.
    2. Export as "line-in.ahsession"
    3. Reconfigure it for System Audio
    4. Export as "system-audio.ahsession"
    5. Then to switch inputs:

      killall 'Audio Hijack' 2>&-
      while ( killall -0 'Audio Hijack' 2>&- ); do sleep 1; done
      rm ~/Library/Application\ Support/Audio\ Hijack/Sessions.plist
      open line-in.ahsession
      osascript -e 'tell application "Audio Hijack" to activate' \
      -e 'tell application "System Events" to keystroke "r" using {command down}'

      This will drop and re-open the connection every time you switch, which is less than ideal, but here we are.

  • Oh, but wait, if Audio Hijack is reading from System Audio, then iShowU gets silence. So you get audio on the Icecast stream and nothing in OBS. Awesome. Having two programs able to read from the same audio source at the same time would be too much to ask. What do you think this is, Linux?

  • The fix to that is to install yet another program, Loopback.

    1. Update both of the saved Audio Hijack configurations to split to two outputs, the Icecast server, as well as to a Loopback input.
    2. Update all of the OBS scenes to take audio from Loopback instead of from iShowU.
    3. Kick iShowU unceremoniously to the curb.

    This means that to fix the bug that Audio Hijack won't play nice and allow iShowU to read at the same time, I had to spend another $100 on Loopback. I would have been a lot more irritated by this if not for the fact that I bought Nicecast from Rogue Amoeba in 2006 and they only made me pay for it once. So, kudos to them for having kept alive the business model where software is a product that you buy rather than a service that you rent. So, yeah, take my money.

  • Oh yeah, and then good luck making the task of "crontab calls osascript which types a keystroke at an app" work. It's a whole other ordeal that involves adding every program under the sun to the list under "System Preferences → Security → Accessiblity", and clicking "Ok" on an endless series of dialogs that will pop up at the most inconvenient possible time.

Previously, previously.

Tags: , , , ,

10 Responses:

  1. Different Jamie says:

    Jesus Christ. Congratulations, I think?

    10.15 broke practically all of the automation I've accumulated, so now my (energy sucking) desktop running linux stays on all the time.

    It is depressing that it is 2020 and once again the choice is functional GUI or functional everything else: pick one.

  2. To address your first point about OBS not having scripting, I stumbled across a WebSocket plugin to control OBS from - https://github.com/Palakis/obs-websocket - which may or may not be useful.

    • Tom says:

      For similar cron-based automation tasks, I've had success sending commands obs-websocket using websocat: https://github.com/vi/websocat

      It's way more reliable than automation using hotkeys, which is what I was doing previously. Protip: If it crashes mysteriously when sending batches of multiple commands, add a brief pause between them. (100 ms worked here)

  3. Thanks for reminding me why I haven't upgraded to 10.15 yet.

  4. Alias Cummins says:

    Yay! Sorry for the red herrings :/

  5. jboy says:

    A Star Wars reference and an Aliens reference? You must feel used, traumatized. What the hell could have done this to a man?

  6. Ryan says:

    I hesitated to mention this during your trials, but given that things are falling apart already, maybe you'll resort to a more fundamental teardown at some point and set aside some minutes to testing it....

    https://github.com/badaix/snapcast

    It doesn't specifically solve your problems, and was built to address a different use-case, and I don't have OSX experience, but it is a smart and good thing for moving audio sources across the network, and should be as scriptable as is possible to be.

    Sorry for what would otherwise certainly be noise, but if you're desperate I hope it could slot in to help somewhere.

    • jwz says:

      In what way do you think that a Linux-only tool that synchronizes audio across a network in multiple rooms has anything even remotely to do with what I am trying to accomplish?

      • Ryan says:

        Well, the build instructions for OSX seemed simple (if buried in the docs).

        And since it creates a pipe for the audio source, even if you only synchronized in one room, that could potentially be more straightforward and/or more reliable than your current setup....

        If OBS is set to consume the pipe, you don't have to press buttons to switch scenes and can instead just switch the source at the server level seamlessly (which would be accessible through cron or whatever other script input you like). And maybe getting your signals to the pipe makes it a non-starter, but it seemed possible to end-around your ffmpeg bug or the issues with track switches you mentioned in the problem post or any of the idiosyncrasies you ran into with the outdated and weird OSX-specific tools.

        Certainly feel free to ignore or exclude, but it wasn't an entirely clueless left field suggestion.

  • Previously