NorskOutput.cmafAudio() method
Produces audio segments with the supplied settings for use in HLS or DASH manifests.
These can optionally be served via the Norsk web server or be pushed to other locations - see CmafDestinationSettings
Signature:
cmafAudio(settings: CmafOutputSettings): Promise<CmafAudioOutputNode>;
Parameters
Parameter | Type | Description |
---|---|---|
settings |
Configuration for the CMAF Audio Stream |
Returns:
Promise<CmafAudioOutputNode>
Example [07_audio_signal.ts]
Generate an audio tone and publish it in an audio-only HLS playlist
export async function main() {
const norsk = await Norsk.connect();
const input = await norsk.input.audioSignal(audioSignalSettings);
const audioOutput = await norsk.output.cmafAudio(hlsAudioSettings);
audioOutput.subscribe([{ source: input, sourceSelector: selectAudio }]);
void audioOutput.url().then(playlistUrl => {
console.log(`playlistUrl: ${playlistUrl}`);
});
}
const audioSignalSettings: AudioSignalGeneratorSettings = {
id: "audio-signal",
sourceName: "signal",
channelLayout: "stereo",
sampleRate: 48000,
wave: mkSine(440),
};
const hlsAudioSettings: CmafOutputSettings = {
id: "hls-audio",
partDurationSeconds: 1.0,
segmentDurationSeconds: 4.0,
destinations: [{ type: "local", retentionPeriodSeconds: 60, id: "local" }],
};
Example [20_cmaf_pull_push.ts]
TODO
export async function main() {
await runWebServer(port);
const norsk = await Norsk.connect();
const input = await norsk.input.rtmpServer({ id: "rtmpInput" });
const destinations: CmafDestinationSettings[] = [
{ type: "local", retentionPeriodSeconds: 60, id: "local" },
{ type: "generic", id: "genericPullPush", host: "localhost", port, pathPrefix: "/push/", retentionPeriodSeconds: 60 }
]
const audioOutput = await norsk.output.cmafAudio({ id: "audio", destinations, ...segmentSettings });
const videoOutput = await norsk.output.cmafVideo({ id: "video", destinations, ...segmentSettings });
const masterOutput = await norsk.output.cmafMultiVariant({ id: "multi-variant", playlistName: "multi-variant", destinations });
audioOutput.subscribe([{ source: input, sourceSelector: selectAudio }]);
videoOutput.subscribe([{ source: input, sourceSelector: selectVideo }]);
masterOutput.subscribe([
{ source: audioOutput, sourceSelector: selectPlaylist },
{ source: videoOutput, sourceSelector: selectPlaylist }
]);
console.log(`Master playlist: ${masterOutput.url}`);
void audioOutput.url().then(logMediaPlaylist("audio"));
void videoOutput.url().then(logMediaPlaylist("video"));
}
Run the following command to generate example input at url rtmp://127.0.0.1:1935/acme/high
:
ffmpeg -v error -re -stream_loop -1 -i data/InkDrop.ts -vcodec copy -codec copy -f flv 'rtmp://127.0.0.1:1935/acme/high'
Example [27_playlist_manipulation.ts]
Manipulate an HLS playlist
export async function main() {
const port = 3210;
await runWebServer(port, { logPlaylists: true });
const norsk = await Norsk.connect();
const input = await norsk.input.rtmpServer({ id: "rtmpInput" });
const localDestination: CmafDestinationSettings = { type: "local", retentionPeriodSeconds: 10, id: "local" };
const pushDestination: CmafDestinationSettings = { type: "generic", id: "gen", host: "localhost", port, pathPrefix: "/push/", retentionPeriodSeconds: 60 }
const destinations: CmafDestinationSettings[] = [
localDestination,
pushDestination
]
const segmentSettings = {
partDurationSeconds: 2.0,
segmentDurationSeconds: 2.0,
};
const audioOutput = await norsk.output.cmafAudio({ id: "audio", destinations, ...segmentSettings });
const videoOutput = await norsk.output.cmafVideo({ id: "video", destinations, ...segmentSettings });
const masterOutput = await norsk.output.cmafMultiVariant({ id: "multi-variant", playlistName: "multi-variant", destinations });
const emptyHlsPlaylist: () => HlsPlaylist = () => {
return {
hlsStandardPlaylist: [],
hlsByteRangePlaylist: [],
hlsFilePartPlaylist: [],
}
}
const audioPlaylistLocal: HlsPlaylist = emptyHlsPlaylist();
const audioPlaylistPush: HlsPlaylist = emptyHlsPlaylist();
audioOutput.onPlaylistAddition = (destinationId: DestinationId, playlistAdditions: HlsPlaylistAdditions): HlsPlaylist => {
if (destinationId == localDestination.id) {
audioPlaylistLocal.hlsFilePartPlaylist.push(...playlistAdditions.hlsFilePartPlaylist);
return audioPlaylistLocal;
} else {
audioPlaylistPush.hlsStandardPlaylist.push(...playlistAdditions.hlsStandardPlaylist, { tag: "# Additional comment line for audio push" });
return audioPlaylistPush;
}
}
const videoPlaylistLocal: HlsPlaylist = emptyHlsPlaylist();
const videoPlaylistPush: HlsPlaylist = emptyHlsPlaylist();
videoOutput.onPlaylistAddition = (destinationId: DestinationId, playlistAdditions: HlsPlaylistAdditions): HlsPlaylist => {
if (destinationId == localDestination.id) {
videoPlaylistLocal.hlsStandardPlaylist.push(...playlistAdditions.hlsStandardPlaylist);
videoPlaylistLocal.hlsFilePartPlaylist.push(...playlistAdditions.hlsFilePartPlaylist);
videoPlaylistLocal.hlsByteRangePlaylist.push(...playlistAdditions.hlsByteRangePlaylist);
return videoPlaylistLocal;
} else {
videoPlaylistPush.hlsStandardPlaylist.push(...playlistAdditions.hlsStandardPlaylist, { tag: "# Additional comment line for video push" });
return videoPlaylistPush;
}
}
audioOutput.subscribe([{ source: input, sourceSelector: selectAudio }]);
videoOutput.subscribe([{ source: input, sourceSelector: selectVideo }]);
masterOutput.subscribe([
{ source: audioOutput, sourceSelector: selectPlaylist },
{ source: videoOutput, sourceSelector: selectPlaylist }
]);
console.log(`Master playlist: ${masterOutput.url}`);
void audioOutput.url().then(logMediaPlaylist("audio"));
void videoOutput.url().then(logMediaPlaylist("video"));
}
Run the following command to generate example input at url rtmp://127.0.0.1:1935/acme/high
:
ffmpeg -v error -re -stream_loop -1 -i data/InkDrop.ts -vcodec copy -codec copy -f flv 'rtmp://127.0.0.1:1935/acme/high'
Find Examples
Search for examples using cmafAudio in our examples repo.