NorskOutput.cmafVideo() method
Produces video segments with the supplied settings for use in HLS or DASH manifests.
These can optionally be served the Norsk web server or be pushed to other locations - see CmafDestinationSettings
Signature:
cmafVideo(settings: CmafOutputSettings): Promise<CmafVideoOutputNode>;
Parameters
Parameter | Type | Description |
---|---|---|
settings |
Configuration for the CMAF Video Stream |
Returns:
Promise<CmafVideoOutputNode>
Example [20_cmaf_pull_push.ts]
TODO
export async function main() {
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}`);
audioOutput.url().then(logMediaPlaylist("audio"));
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;
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}`);
audioOutput.url().then(logMediaPlaylist("audio"));
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 cmafVideo in our examples repo.