In the first part we have deployed a simple dynamic CDN for broadcasting WebRTC streams to two continents and have proved on the example of a countdown timer that the latency in this kind of CDN is actually low.

However, besides low latency, it is important to provide good broadcast quality to users. After all, this is what they are paying for. In real life the channels between Edge servers and users can differ in bandwidth capacity and quality. For example, we are publishing a 720p stream at 2 Mbps, the user is playing it on an Android phone using 3G connection in an unstable signal reception area and the 360p maximum resolution that provides smooth picture at 400 Mbps is 360p.

The devices and browsers the viewers are using may differ a lot. For example, we are publishing a WebRTC stream using VP8 codec in Chrome on PC and the viewer is playing the stream in Safari on an iPhone, which supports only H264 codec. Or vice versa, we are publishing an RTMP stream from OBS Studio, coding the video in H264 and the sound in AAC, and the client is using a Chromium-based browser which supports only VP8 or VP9 for the video and Opus for the sound.

We may need as well to enhance the quality of the initial publishing. For example, we are sharing a stream from an IP-camera in a natural park, most of the time the picture is static, and the camera is delivering it at 1 frame per second. However, we want to provide to viewers 24 frames per second. What is to be done, if there is no possibility to replace the camera or modify its settings?

In all these cases we will need to transcode the stream on the server, that is decode each received frame and then encode it with new parameters. Besides, the parameters to be modified are often only known on the client’s side. Let’s have a look at how to achieve transcoding in CDN while keeping a balance between broadcast quality and server load.

 

Transcoding: how, where and why?

Assume we are aware of the stream parameters the client wants to receive. For example, the viewer has begun playing the stream, and the number of frame losses in WebRTC statistics tells us that the resolution and bitrate need to be reduced before the client switches to another show. In this case. the stream will be transcoded by default on the Edge server the viewer is connected to

Dynamic CDN for Low Latency WebRTC Streaming with Transcoding Stream transcoding on Edge servers

If the client does not support the codec used during stream publishing, the transcoding can be imposed both on Edge and Origin servers.

Both these methods only work as a temporary solution on condition that Origin and/or Edge server configurations are set with a margin. Trascoding is always performed frame by frame, therefore it is very demanding of the CPU resources. Thus, a single CPU core is able to transcode just a small number of streams:

Resolution Bitrate, Kbps Number of streams
360p 1300 5
480p 1800 3
720p 3000 2

 

Even if we are going to run a single transcoding process for all the users needing equal media stream parameters, it is highly probable that a few viewers with different parameters will entirely consume the server resources.
In this manner, the right decision is to set apart dedicated servers in the CDN to carry out the task of transcoding and choose the server configuration bearing in mind this task.

 

Adding Transcoder nodes into CDN

Now, we are going to deploy two Transcoder servers in our CDN: one in the European data center and one in the American

Dynamic CDN for Low Latency WebRTC Streaming with Transcoding CDN with transcoders scheme

Setup of Transcoder servers:

  • Transcoder 1 EU
cdn_enabled=true
cdn_ip=t-eu1.flashphoner.com
cdn_point_of_entry=o-eu1.flashponer.com 
cdn_nodes_resolve_ip=false 
cdn_role=transcoder
  • Transcoder 1 US
cdn_enabled=true 
cdn_ip=t-us1.flashphoner.com 
cdn_point_of_entry=o-eu1.flashponer.com 
cdn_nodes_resolve_ip=false 
cdn_role=transcoder

Stream transcoding parameters should be described on Edge servers by means of special profiles in the cdn_profiles.yml file. As an example, look at the three profiles used by default:

  • transcoding to 640×360 resolution, 30 frames per second, the keyframe will be sent every 90 frames, H264 video codec using OpenH264 encoder, Opus 48 kHz audio codec.
-640x360:
        audio:
          codec : opus
          rate : 48000
        video:
          width : 640
          height : 360
          gop : 90
          fps : 30
          codec : h264
          codecImpl : OPENH264
  • transcoding to 1280×720 resolution, H264 video codec using OpenH264 encoder, with no audio transcoding.
 -720p:
        video:
          height : 720
          codec : h264
          codecImpl : OPENH264

 

  • transcoding to 1280×720 resolution, 30 frames per second, the keyframe will be sent every 90 frames, 2Mbps bitrate, H264 video codec using OpenH264 encoder, with no audio transcoding.
-720p-2Mbps:
        video:
          height : 720
          bitrate : 2000
          gop : 90
          fps : 30
          codec : h264
          codecImpl : OPENH264


Let’s publish the 720p test stream on the o-eu1 server and play the stream on e-eu1 specifying the profile in the stream name, for example, test-640×360

Dynamic CDN for Low Latency WebRTC Streaming with Transcoding Stream publishing and playback
The stream is being transcoded!

Now we can describe a number of profiles on Edge servers, for example, -240p, -360p, -480p and, if a large number of lost frames are diagnosed on the client’s side according to WebRTC statistics, we can automatically repeat the request for a lower resolution stream.

 

Grouping CDN nodes per continents

Currently we have peer Transcoder servers. But what if we want to transcode the streams based on the geographical spread: for the American viewers in America, for the European viewers in Europe? By the way, this will allow to reduce the load on the transatlantic channels, because the Origin EU server will transmit to America and receive back only the original streams rather than all the variants of transcoded ones

Dynamic CDN for Low Latency WebRTC Streaming with Transcoding CDN with transcoders and location groups scheme

In this case, it is necessary to specify the required CDN group in the Transcoder node settings

  • Transcoder 1 EU
cdn_enabled=true
cdn_ip=t-eu1.flashphoner.com
cdn_point_of_entry=o-eu1.flashponer.com
cdn_nodes_resolve_ip=false
cdn_role=transcoder
cdn_groups=EU
  • Transcoder 1 US
cdn_enabled=true
cdn_ip=t-us1.flashphoner.com
cdn_point_of_entry=o-eu1.flashponer.com<
cdn_nodes_resolve_ip=false
cdn_role=transcoder
cdn_groups=US

Also, the group has to be added to Edge server settings.

  • Edge 1-2 EU
cdn_groups=EU
  • Edge 1-2 US
cdn_groups=US

Let’s restart the nodes with new settings. Then, let’s publish the 720p test stream on the o-eu1 server and play this stream on e-eu1 with transcoding

Dynamic CDN for Low Latency WebRTC Streaming with Transcoding Stream publishing and playback

In order to make sure that the stream is being transcoded on t-eu, we have to open the statistics page at http://t-eu1.flashphoner.com:8081/?action=stat, and we will see the encoder and the decoder in Native resources section

Dynamic CDN for Low Latency WebRTC Streaming with Transcoding Statistics displayed while transcoding one stream

Moreover, there are no video encoders on t-us1 in the statistics

Dynamic CDN for Low Latency WebRTC Streaming with Transcoding Statistics displayed when no stream transcoding

 

More transcoders: balancing the load

Assume the number of viewers keeps increasing and the capacity of one Transcoder server per continent is not enough anymore. Great, let’s add one more server for each continent

Dynamic CDN for Low Latency WebRTC Streaming with Transcoding CDN with 2 transcoders by group scheme

  • Transcoder 2 EU
cdn_enabled=true
cdn_ip=t-eu2.flashphoner.com
cdn_point_of_entry=o-eu1.flashponer.com
cdn_nodes_resolve_ip=false
cdn_role=transcoder
cdn_groups=EU
  • Transcoder 2 US
cdn_enabled=true
cdn_ip=t-us2.flashphoner.com
cdn_point_of_entry=o-eu1.flashponer.com
cdn_nodes_resolve_ip=false
cdn_role=transcoder
cdn_groups=US

Now, however, we experience the issue of balancing the load between two transcoders. To avoid transmitting all the streams through one server, we are going to set the threshold for the maximum allowable CPU load average on Transcoder nodes.

cdn_node_load_average_threshold=0.95

When the CPU load average divided by the number of available cores will reach this threshold, the server will stop accepting requests for transcoding new streams.
We can also set a limit to the maximum allowable number of simultaneously running video encoders.

cdn_transcoder_video_encoders_threshold=10000

When this number is reached, the server will also stop accepting requests for stream transcoding, even if the CPU load still allows it.
Anyway, Transcoder server will keep sharing the streams that are being transcoded on it to Edge servers.

 

To be concluded

To sum up, we have deployed in our CDN dedicated servers for transcoding media streams and, thus, are able to provide good broadcast quality to our viewers depending on the capabilities of their devices and the quality of the channels. However, we have not touched upon the subject of stream access restriction yet. We will have a look at this in the final part.