# Send an adaptive bitrate stream to Akamai The Stream Targets feature in Wowza Streaming Engine™ [media server software](https://www.wowza.com/products/streaming-engine) allows you to send live streams to widely distributed destinations. This article explains how to use the **group-manager** profile to create stream targets with the Wowza Streaming Engine REST API to send adaptive bitrate live streams to Akamai for HLS and MPEG-DASH distributed delivery. Using the **group-manager** profile, you can group multiple bitrate stream renditions and send the group to Akamai with a single stream target. The group contains the streams you specify and uses a unique, adaptive bitrate playback URL. This article assumes you have already created a Wowza Streaming Engine application with adaptive bitrate streams for playback with HLS or MPEG-DASH and configured Akamai to ingest an HLS or MPEG-DASH stream. See [Configure Akamai to receive and distribute the stream](https://www.wowza.com/docs/how-to-stream-to-akamai#configure-akamai-to-receive-and-distribute-the-stream) to configure Akamai. Refer to the Akamai documentation if you need additional help with configuring its service to ingest adaptive bitrate streams. > **Note:** Using the **group-manager** profile is the most efficient way to stream adaptive bitrate content to Akamai and is not supported in Wowza Streaming Engine Manager. In addition to using the REST API to send adaptive bitrate streams to Akamai with a single stream target, you can also edit the **PushPublishMap.txt** file directly to do so. See [Stream to the Akamai HD network from Wowza Streaming Engine](https://www.wowza.com/docs/how-to-stream-to-akamai) for more information. ## Enable push publishing in the Wowza Streaming Engine REST API Before you can create or use stream targets with the Wowza Streaming Engine REST API, you must enable the push publishing module. To do so, you need to add an advanced property to the application's configuration and add the push publish module to the application. Start by retrieving the details of the application's advanced settings and a list of the modules the application is using. Retrieve the information by sending a GET call to the endpoint **/v2/servers/{serverName}/vhosts/{vhostName}/applications/{appName}/adv**. > **Note:** Wowza Streaming Engine REST API requests must include three headers: Accept:application/json, Content-Type:application/json, and charset=utf-8. For more information, see [Query the Wowza Streaming Engine REST API](https://www.wowza.com/docs/how-to-query-the-wowza-streaming-engine-rest-api). Example request: ```bash curl -X GET \ -H 'Accept:application/json; charset=utf-8' \ -H 'Content-Type:application/json; charset=utf-8' \ "http://localhost:8087/v2/servers/{serverName}/vhosts/{vhostName}/applications/{appName}/adv" ``` The request returns an **advancedSettings** object that shows the application's advanced settings and a **modules** list of the modules in use. The response looks like this: ```json { "version": "1543353224014", "serverName": "serverName", "advancedSettings": [ { "enabled": false, "canRemove": true, "name": "debugAACTimecodes", "value": "false", "defaultValue": "false", "type": "Boolean", "sectionName": "cupertinostreamingpacketizer", "section": "/Root/Application/LiveStreamPacketizer", "documented": true }, { "enabled": false, "canRemove": true, "name": "debugMP3Timecodes", "value": "false", "defaultValue": "false", "type": "Boolean", "sectionName": "cupertinostreamingpacketizer", "section": "/Root/Application/LiveStreamPacketizer", "documented": true }, ... ], "modules": [ { "order": 0, "name": "base", "description": "Base", "class": "com.wowza.wms.module.ModuleCore" }, { "order": 1, "name": "logging", "description": "Client Logging", "class": "com.wowza.wms.module.ModuleClientLogging" }, { "order": 2, "name": "flvplayback", "description": "FLVPlayback", "class": "com.wowza.wms.module.ModuleFLVPlayback" }, { "order": 3, "name": "ModuleCoreSecurity", "description": "Core Security Module for Applications", "class": "com.wowza.wms.security.ModuleCoreSecurity" } ] } ``` > **Note:** During GET requests to the `/v2/servers/{serverName}/vhosts/(vhostName}/applications/{appName}/adv` endpoint, the **wowzaVideoApiToken** used for Wowza Video stream targets is obfuscated. When you run a PUT or POST request for this same endpoint, the **wowzaVideoApiToken** is encrypted when stored. Now, execute a PUT command to accomplish two tasks: - Add the **pushPublishMapPath** property to the application's configuration. - Append the **ModulePushPublish** to the complete list of modules in use. > **Note:** The PUT command must include all of the existing modules in use by the application as well as the push publish module; use the response from the GET call to enumerate the modules that precede **ModulePushPublish** in the PUT call. The command calls the same endpoint, `/v2/servers/{serverName}/vhosts/(vhostName}/applications/{appName}/adv`, and looks like this: > **Note:** During GET requests to the `/v2/servers/{serverName}/vhosts/(vhostName}/applications/{appName}/adv` endpoint, the `wowzaVideoApiToken` used for Wowza Video stream targets is obfuscated. When you run a PUT or POST request for this same endpoint, the wowzaVideoApiToken is encrypted when stored. Now, execute a PUT command to accomplish two tasks: - Add the `pushPublishMapPath` property to the application's configuration. - Append the `ModulePushPublish` to the complete list of modules in use. > **Note:** The PUT command must include all of the existing modules in use by the application as well as the push publish module; use the response from the GET call to enumerate the modules that precede ModulePushPublish in the PUT call. The command calls the same endpoint, `/v2/servers/{serverName}/vhosts/(vhostName}/applications/{appName}/adv`, and looks like this: ```json curl -X PUT \ -H 'Accept:application/json; charset=utf-8' \ -H 'Content-Type:application/json; charset=utf-8' \ "http://localhost:8087/v2/servers/{serverName}/vhosts/{vhostName}/applications/{appName}/adv" { "version": "1543353224014", "serverName": "serverName", "advancedSettings": [ { "enabled": true, "canRemove": false, "name": "pushPublishMapPath", "value": "${com.wowza.wms.context.VHostConfigHome}/conf/${com.wowza.wms.context.Application}/PushPublishMap.txt", "defaultValue": null, "type": "String", "sectionName": "Application", "section": "/Root/Application", "documented": false } ], "modules": [ { "order": 0, "name": "base", "description": "Base", "class": "com.wowza.wms.module.ModuleCore" }, { "order": 1, "name": "logging", "description": "Client Logging", "class": "com.wowza.wms.module.ModuleClientLogging" }, { "order": 2, "name": "flvplayback", "description": "FLVPlayback", "class": "com.wowza.wms.module.ModuleFLVPlayback" }, { "order": 3, "name": "ModuleCoreSecurity", "description": "Core Security Module for Applications", "class": "com.wowza.wms.security.ModuleCoreSecurity" }, { "order": 4, "name": "ModulePushPublish", "description": "ModulePushPublish", "class": "com.wowza.wms.pushpublish.module.ModulePushPublish" } ] } ``` Finally, restart the application, and then you can create and edit stream targets using the Wowza Streaming Engine REST API. ```bash curl -X PUT \ -H 'Accept:application/json; charset=utf-8' \ "http://localhost:8087/v2/servers/{serverName}/vhosts/{vhostName}/applications/{appName}/actions/restart" ``` ## Create an Akamai stream target in Wowza Streaming Engine With the Wowza Streaming Engine REST API, use your Akamai stream information from the Media Services Live page in Luna Control Center to create an Akamai stream target for an application *{appName}* using the **group-manager** profile to group adaptive bitrate streams. **Map entries parameters:** | Parameter | Data Type | Description | | --- | --- | --- | | *profile* (required) | String | Specify **group-manager**. | | *childProfile* (required) | String | Defines how streams in the group are sent to a destination and determines which additional configurable parameters are available. Supported values: **cupertino-akamai** (use to send a group of streams to an HLS Akamai stream) or **mpegdash-akamai** (use to send a group of streams to an MPEG-DASH Akamai stream). | | *group.streamMatcher* (required) | String | Determines the method of identifying streams to group for delivery to the destination and how to identify the source streams as **sourceStreamName**. Use one of the following options: nameList - Use to identify streams with a list of one or more stream names separated with the pipe character (|). For example, with "group.streamMatcher":"nameList", sourceStreamName could be myStream_160p myStream_720p.nameRegex - Use to identify streams using a regular expression. For example, with "group.streamMatcher":"nameRegex", sourceStreamName could be my[sSdDqQ]tream.+.namePrefix - Use to identify streams by a shared prefix in stream names. For example, with "group.streamMatcher":"namePrefix", sourceStreamName could be myStream, which would group any streams with names that begin with myStream.ngrp - Use to identify streams in a stream name group. For example, with "group.streamMatcher":"ngrp", sourceStreamName could be myStream_all.smil - Use to identify streams included in a SMIL file in [install-dir]/content. For example, with "group.streamMatcher":"smil", sourceStreamName could be myStream.smil.amlst - Use to identify streams included in an AMLST file provided by an IMediaListProvider module. For example, with "group.streamMatcher":"amlst", sourceStreamName could be myStream.amlst. | | *sourceStreamName* (required) | String | Specify the streams to include in the stream group according to the method defined with **group.streamMatcher**. | | *group.name* (required) | String | A descriptive name for the stream group for this stream target, used to identify the group in playback URLs. | | *entryName* (required) | String | A descriptive name for the map entry — for example, **Akamai-DASH-myStreamNGRP**. | | *akamai.streamId* (required) | String | Destination Akamai StreamId. | | *playbackHost* | String | **For Akamai MSL 4 networks:** The hostname or IP address of the server from which the stream will be played. Required with Akamai MSL 4 if **http.relativePlaylists** is not enabled (absolute URL references in the playlists and manifests sent to the destination). We recommend providing **playbackHost** to include this value, rather than a placeholder, in the playback URLs in Wowza Streaming Engine logs. | | *akamai.hostId* | String | **For Akamai MSL 3 networks:** The host ID for the provisioned stream as it appears in the hostname column for the stream configuration in the Luna Control Center. Specifically, the host ID portion of the Akamai hostname is to the left of the first period in the name. For targets that use the Akamai MSL 3 network, you must provide either **akamai.hostId** or **host**. Required with Akamai MSL 3 under the following conditions: if http.relativePlaylists is not enabledif host is not provided and http.relativePlaylists is enabled We recommend providing **akamai.hostID** to include this value, rather than a placeholder, in the playback URLs in Wowza Streaming Engine logs. | | *host* | String | **For Akamai MSL 3 networks:** The hostname or IP address of the Akamai server that the source stream will be sent to. For targets that use the Akamai MSL 3 network, you must provide either **host** or **akamai.hostId**. Required with Akamai MSL 3 if akamai.hostId is not provided. | | *akamai.destinationServer* | String | Destination Akamai server(s) to send a redundant stream to for failover in case of a problem with the primary stream. Wowza Streaming Engine sends the redundant stream to the backup entry point at Akamai. Valid values are: **primary**, **backup**, or **redundant**. A single map entry is pushed to both primary and backup servers when **redundant** is specified. Specifying **redundant** also generates a separate redundancy manifest/playlist that provides playback URLs for both the primary and backup streams. | | *http.playlistCount* | Integer | The number of chunks to maintain in the playlist. The default, **0**, means the live stream packetizer **PlaylistChunkCount** property value in the application configuration specifies the playlistCount: **cupertinoPlaylistChunkCount** property - default is **3** **mpegdashPlaylistSegmentCount** property - default is **5** | | *http.relativePlaylists* | Boolean | Set to **true** to use only relative URL references in the playlists and manifests sent to the destination. The default is **false**. | | *mpegdash.audioRepresentationId* | String | Defines a unique ID string for the stream's audio component, which modifies the ID attribute of the Representation element in the MPEG-DASH MPD manifest file. Can be any alphanumeric string. If not provided, the identifier is constructed from the bitrate value in kilobits per second. For example, **audio_752kbps**. | | *mpegdash.videoRepresentationId* | String | Defines a unique ID string for the stream's video component, which modifies the ID attribute of the Representation element in the MPEG-DASH MPD manifest file. Can be any alphanumeric string. If not provided, the identifier is constructed from the bitrate value in kilobits per second. For example, **video_752kbps**. | | *debugLog* | Boolean | Set to **true** to turn on debug connection logging. The default is **false**. | | *debugLogChildren* | Boolean | Set to **true** to turn on debug logging of the child push publishing sessions. The default is **false**. | **Example request and response:** ```bash curl -X POST \ -H 'Accept:application/json; charset=utf-8' \ -H 'Content-Type:application/json; charset=utf-8' \ http://localhost:8087/v2/servers/{serverName}/vhosts/{vhostName}/applications/{appName}/pushpublish/mapentries/Akamai-DASH-myStreamNGRP \ -d '{ "profile": "group-manager", "childProfile": "mpegdash-akamai", "group.streamMatcher": "ngrp", "sourceStreamName": "myStream_all", "group.name": "NameGroupDASH", "entryName": "Akamai-DASH-myStreamNGRP", "akamai.streamId": "123456", "playbackHost": "example-i", "akamai.destinationServer": "primary", "http.playlistCount": "15", "debugLog": "true", "debugLogChildren": "true" }' ``` The command creates the target (map entry) and returns a response that looks like this: ```json { "success": true, "message": "Entry (Akamai-DASH-myStreamNGRP) saved successfully", "data": null } ``` Map entry added to **PushPublishMap.txt**: ```text myStream_all={"entryName":"Akamai-DASH-myStreamNGRP", "profile":"group-manager", "group.name":"NameGroupDASH", "playbackHost":"example-i", "debugLog":"true", "debugLogChildren":"true", "akamai.streamId":"123456", "http.playlistCount":"15", "childProfile":"mpegdash-akamai", "group.streamMatcher":"ngrp" ``` > **Note:** Stream targets created using the **group-manager** profile do not appear in Wowza Streaming Engine Manager. **Related request:** Enable a single stream target (push publishing map entry): ```bash curl -X PUT \ -H "Accept:application/json" \ -H "charset=utf-8" \ -H "Content-Type:application/json" \ "http://localhost:8087/v2/servers/{serverName}/vhosts/{vhostName}/applications/{appName}/pushpublish/mapentries/{entryName}/actions/enable" ``` ## Test the connection 1. Start the stream in the camera or encoder that's sending the stream to the live application in Wowza Streaming Engine. The application ingests the live stream and sends it to Akamai. 2. In Luna Control Center, verify that Akamai is receiving the stream and distributing it to endpoints across its network. - Click the **Monitor** menu, choose **Monitor Streams**, and then choose the product. - Check to see that there's an **Ingest Bit Rate** and an **Egress Bit Rate** for your stream. 3. Enter the playback URL(s) in a test player. You can use your own player or the [Video Test Players](https://www.wowza.com/testplayers) web page. In the following example playback URLs, *[akamai-playback-host]* is the playback hostname for the stream as it appears in the Luna Control Center. **HLS:** ``` http://[akamai-playback-host].akamaihd.net/hls/live/[akamai.streamId]/[group.name]/playlist.m3u8 ``` **MPEG-DASH:** ``` http://[akamai-playback-host].akamaihd.net/dash/live/[akamai.streamId]/[group.name]/manifest.mpd ``` 4. Stop the stream in the source camera or encoder to end your test connection. ## More resources - [Stream to the Akamai HD network from Wowza Streaming Engine](https://www.wowza.com/docs/how-to-stream-to-akamai) - [Use CDNs and services to distribute live streams from Wowza Streaming Engine](https://www.wowza.com/docs/how-to-push-streams-to-cdns-and-other-services-push-publishing) - [Sample map file entries for Stream Target destinations (push publishing)](https://www.wowza.com/docs/sample-map-file-entries-for-stream-target-destinations-push-publishing)