Skip to main content

IVS Broadcast Sink Node

The IVSBroadcastSinkNode is the bridge between a Switchboard audio graph and an Amazon IVS stream. Any audio routed into this node is forwarded to a custom audio source attached to your IVS broadcast session (Low-Latency) or stage (Real-Time), so the processed Switchboard mix is what your audience hears.

The node has a single input and no outputs. Its type string in a graph configuration is AmazonIVS.Sink.


Configuration​

This node has no JSON configuration options. The Amazon IVS audio source is provided at runtime through the customAudioSource property (see below).


Properties​

customAudioSource​

A pointer to the Amazon IVS audio source the node writes into.

  • On iOS this is the IVSCustomAudioSource created from your IVSBroadcastSession (Low-Latency) or IVSDeviceDiscovery (Real-Time). Bind it with Switchboard.setValue(...).
  • On Android the audio source is an IVS AudioDevice created from the BroadcastSession; it is passed directly to the IVSBroadcastSinkNode constructor when building the graph programmatically.

The node also inherits properties from its parent, SingleBusAudioSinkNode.


Actions​

Inherits actions from its parent, SingleBusAudioSinkNode.


Events​

Inherits events from its parent, SingleBusAudioSinkNode.


Audio format​

The node converts the Switchboard bus into the format expected by the Amazon IVS audio source at the engine's sample rate:

PlatformFormatChannels
iOS32-bit float (non-interleaved), delivered as a CMSampleBufferStereo
Android16-bit PCM (AudioDevice.Format.INT16)Mono / multi-channel

On Android the IVS AudioDevice is created at the engine sample rate and is commonly mono, so place a ChannelSplitter (or otherwise produce a single-channel bus) ahead of the sink when the source path is stereo.


Example

The graph below plays an audio file, monitors it locally, and feeds the mixed signal (file plus microphone) into the AmazonIVS.Sink node, which forwards it to your IVS stream.

{
"type": "Switchboard.Realtime",
"config": {
"microphoneEnabled": true,
"graph": {
"nodes": [
{ "id": "audioPlayer", "type": "AudioPlayer" },
{ "id": "splitterNode", "type": "BusSplitter" },
{ "id": "mixerNode", "type": "Mixer" },
{ "id": "ivsSinkNode", "type": "AmazonIVS.Sink" }
],
"connections": [
{ "sourceNode": "audioPlayer", "destinationNode": "splitterNode" },
{ "sourceNode": "splitterNode", "destinationNode": "mixerNode" },
{ "sourceNode": "inputNode", "destinationNode": "mixerNode" },
{ "sourceNode": "mixerNode", "destinationNode": "ivsSinkNode" },
{ "sourceNode": "splitterNode", "destinationNode": "outputNode" }
]
}
}
}

After creating the engine from this graph, bind your IVS audio source to the ivsSinkNode and start the engine alongside the IVS broadcast.

Low-Latency (iOS)​

import AmazonIVSBroadcast
import SwitchboardAmazonIVSLowLatency
import SwitchboardSDK

// 1. Create an IVS broadcast session with a custom audio source.
let config = IVSBroadcastConfiguration()
config.mixer.slots.first?.preferredAudioInput = .userAudio

let broadcastSession = try IVSBroadcastSession(configuration: config, descriptors: nil, delegate: self)
let customAudioSource = broadcastSession.createAudioSource(withName: "custom-audio-source")
broadcastSession.attach(customAudioSource, toSlotWithName: "default")

// 2. Create the Switchboard engine from a graph containing an AmazonIVS.Sink node.
let engineJSON = try String(contentsOf: Bundle.main.url(forResource: "SimpleStream", withExtension: "json")!, encoding: .utf8)
let engineID = Switchboard.createEngine(withJSON: engineJSON).value! as String

// 3. Bind the IVS audio source to the sink node.
Switchboard.setValue(customAudioSource, forKey: "customAudioSource", onObject: "ivsSinkNode")

// 4. Start the engine and the broadcast.
Switchboard.callAction(withObject: engineID, actionName: "start", params: nil)
try broadcastSession.start(with: rtmpsUrl, streamKey: streamKey)

Real-Time (iOS)​

import AmazonIVSBroadcast
import SwitchboardAmazonIVSRealTime
import SwitchboardSDK

// 1. Create a custom audio source and publish it to an IVS stage.
let deviceDiscovery = IVSDeviceDiscovery()
let customAudioSource = deviceDiscovery.createAudioSource(withName: "custom-audio-source")
localStreams.append(IVSLocalStageStream(device: customAudioSource))

let stage = try IVSStage(token: token, strategy: self)

// 2. Create the Switchboard engine and bind the IVS audio source to the sink node.
let engineJSON = try String(contentsOf: Bundle.main.url(forResource: "SimpleStage", withExtension: "json")!, encoding: .utf8)
let engineID = Switchboard.createEngine(withJSON: engineJSON).value! as String
Switchboard.setValue(customAudioSource, forKey: "customAudioSource", onObject: "ivsSinkNode")

// 3. Start the engine and join the stage.
Switchboard.callAction(withObject: engineID, actionName: "start", params: nil)
try stage.join()

Android​

On Android the graph is built programmatically and the IVS AudioDevice is passed straight to the node constructor.

val audioGraph = AudioGraph()
val audioEngine = AudioEngine(context)
val audioPlayerNode = AudioPlayerNode()
val busSplitterNode = BusSplitterNode()
val channelSplitterNode = ChannelSplitterNode()

// Create the IVS broadcast session and a custom AudioDevice source (mono, INT16, engine sample rate).
val session = BroadcastSession(context, broadcastListener, broadcastConfiguration, null)
val audioDevice = session.createAudioInputSource(1, sampleRate, AudioDevice.Format.INT16)

// Build the sink node from the AudioDevice.
val ivsSinkNode = IVSBroadcastSinkNode(audioDevice!!)

audioGraph.addNode(audioPlayerNode)
audioGraph.addNode(busSplitterNode)
audioGraph.addNode(channelSplitterNode)
audioGraph.addNode(ivsSinkNode)

audioGraph.connect(audioPlayerNode, busSplitterNode)
audioGraph.connect(busSplitterNode, channelSplitterNode)
audioGraph.connect(channelSplitterNode, ivsSinkNode)
audioGraph.connect(busSplitterNode, audioGraph.outputNode)

// Start the engine and the broadcast.
audioEngine.start(audioGraph)
session.start(endpoint, streamKey)
tip

For complete, runnable references see the Simple Stream (Low-Latency) and Simple Stage (Real-Time) examples in the iOS sample app, and the Karaoke App with Amazon IVS walkthrough.