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

CmafOutputSettings

Configuration for the CMAF Audio Stream

Returns:

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 }]);

  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() {
  webServer.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;
  webServer.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: [],
    }
  }

  let audioPlaylistLocal: HlsPlaylist = emptyHlsPlaylist();
  let 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;
    }
  }

  let videoPlaylistLocal: HlsPlaylist = emptyHlsPlaylist();
  let 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