orange icon indicating copy to clipboard operation
orange copied to clipboard

Cloudflare Publishes 640x360 Video Instead of 1080p on adding track into the session

Open dakshcladbe opened this issue 7 months ago • 1 comments

Cloudflare api is publising the low quality stream even sending the high resolution The published video track is 640x360 with a bitrate of 5.03 Mbps. 640x360 is the stats of outbound of the cloudflare peer connection

Our WebRTC application, built with flutter_webrtc and Cloudflare's Selective Forwarding Unit (SFU), is publishing a video track at 640x360 resolution with a bitrate of 5.03 Mbps, despite being explicitly configured to publish a 1080p (1920x1080) video track. The application requests user media with exact 1080p constraints, adds a single video track with 4 Mbps encoding, and sends it to Cloudflare's /apps/{appId}/sessions/{sessionId}/tracks/new endpoint. The goal is to publish only a 1080p video track (no audio or other resolutions) and subscribe to it. However, WebRTC stats show the published track is consistently 640x360.

Steps to Reproduce

Initialize WebRTC Session:

Use flutter_webrtc in a Flutter app to create a peer connection.

Connect to Cloudflare's SFU via https://rtc.live.cloudflare.com.

Request User Media:

Configure constraints for 1080p video, disabling audio:

{ 'audio': false, 'video': { 'facingMode': 'user', 'width': {'exact': 1920}, 'height': {'exact': 1080}, 'frameRate': {'exact': 30}, }, } Log confirms camera settings:

[log] Video track settings: width=1920, height=1080, frameRate=30

Add Video Track:

Add a single video track to the peer connection with encoding parameters:

RTCRtpTransceiverInit( direction: TransceiverDirection.SendOnly, sendEncodings: [ RTCRtpEncoding( maxBitrate: 4000000, // 4 Mbps minBitrate: 1500000, scaleResolutionDownBy: 1.0, // No scaling active: true, ), ], )

Log confirms track settings before publishing:

[log] Video track settings in adding tracks api session: width=1920, height=1080, frameRate=30

Publish Track:

Create an SDP offer and send it to Cloudflare's /apps/{appId}/sessions/{sessionId}/tracks/new endpoint.

Publish the track via WebSocket with a trackPublished message.

Relevant code snippet from _addTrackToSession:

final requestBody = { 'sessionDescription': {'type': 'offer', 'sdp': completeSdp.sdp}, 'tracks': [ { 'location': 'local', 'trackName': videoTrack.id, 'kind': 'video', 'sessionId': sessionId, 'mid': midValues.isNotEmpty ? midValues[0] : '0', }, ], }; final response = await http.post( Uri.parse('https://rtc.live.cloudflare.com/v1/apps/$_appId/sessions/$sessionId/tracks/new'), headers: { 'Authorization': 'Bearer $_appSecret', 'Content-Type': 'application/json', }, body: jsonEncode(requestBody), );

Monitor Video Quality:

Use WebRTC stats to check the published track's resolution and bitrate:

final stats = await _peerConnection!.getStats(); for (var report in stats) { if (report.type == 'outbound-rtp' && report.values['mediaType'] == 'video') { final width = report.values['frameWidth'] ?? 0; final height = report.values['frameHeight'] ?? 0; final bitrate = report.values['bytesSent'] != null ? (report.values['bytesSent'] * 8 / 1000000).toStringAsFixed(2) : 'unknown'; dev.log("Published video quality: ${width}x${height}, bitrate: $bitrate Mbps"); } }

Expected Behavior

The published video track should be 1920x1080 (1080p) with a bitrate around 4 Mbps.

Logs should show:

[log] Video track settings: width=1920, height=1080, frameRate=30 [log] Published video quality: 1920x1080, bitrate: ~4.00 Mbps

Actual Behavior

The published video track is 640x360 with a bitrate of 5.03 Mbps.

Logs show:

[log] Attempting to set exact video constraints: 1920x1080 @ 30fps (1080p)... [log] Video track settings: width=1920, height=1080, frameRate=30 [log] Video track settings in adding tracks api session: width=1920, height=1080, frameRate=30 [log] Published video quality: 640x360, bitrate: 5.03 Mbps

How can i fix this to publised the same video tracks quality to cloudflare sfu or turn

dakshcladbe avatar May 28 '25 12:05 dakshcladbe

I think there are a couple of points here:

The most important one is that you hopefully understand that you are using WebRTC, which is quite different from streaming on YouTube. In webrtc there is no way to guarantee the outgoing stream quality. The encoder on the sender side will try it's best to push the outgoing video through the connection with the main goal being to keep a reasonable frame rate on the receiver side.

My best guess from your description is that the encoder thinks there isn't sufficient bandwidth on your uplink to send the video with 720p, thus it scales it down to 360p instead.

I would recommend you to remove the scaleResolutionDownBy from the sendEncodings, because it doesn't help and might lead to confusion as it is normally used to turn simulcast, which it sound like you actually don't want right now.

Secondly I would recommend you to try raising the maxBitrate setting in your sendEncodings and see if you can find a value which results in 720p getting send out.

Lastly, in case you are not ware of it yet, I would highly recommend you to take a look at chrome://webrtc-internals and check the values for your outgoing video stream as it might give you hints on why 720p isn't send.

nils-ohlmeier avatar May 28 '25 17:05 nils-ohlmeier