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
IVSCustomAudioSourcecreated from yourIVSBroadcastSession(Low-Latency) orIVSDeviceDiscovery(Real-Time). Bind it withSwitchboard.setValue(...). - On Android the audio source is an IVS
AudioDevicecreated from theBroadcastSession; it is passed directly to theIVSBroadcastSinkNodeconstructor 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:
| Platform | Format | Channels |
|---|---|---|
| iOS | 32-bit float (non-interleaved), delivered as a CMSampleBuffer | Stereo |
| Android | 16-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.
- Graph JSON
{
"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)​
- Swift
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)​
- Swift
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.
- Kotlin
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)
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.