MacOS 10.13 Safari 11中WebRTC PeerConnection显示黑屏问题排查
Hey there! Let's dig into why Safari 11 is showing a black screen instead of your Raspberry Pi camera feed. I've gone through your code and setup details, here are key issues to check and fix:
Your pcOptions uses the old deprecated optional array syntax for DtlsSrtpKeyAgreement, which Safari 11 (a standards-aligned but early WebRTC implementation) doesn't handle correctly. The modern standard expects this as a direct boolean property:
// Replace this var pcOptions = {optional: [{DtlsSrtpKeyAgreement: true}]}; // With this var pcOptions = { dtlsSrtpKeyAgreement: true };
The old syntax was tied to legacy WebKit-prefixed APIs, and using it can break DTLS handshake in Safari—preventing media encryption and stream delivery.
When adding ICE candidates, you're missing the sdpMid parameter, which Safari 11 requires to properly map candidates to the media stream. Fix the candidate creation:
// Replace this var candidate = new RTCIceCandidate({sdpMLineIndex: dataJson.label, candidate: dataJson.candidate}); // With this var candidate = new RTCIceCandidate({ sdpMLineIndex: dataJson.label, sdpMid: dataJson.id, // Add this line to pass the sdpMid from the incoming candidate candidate: dataJson.candidate });
Without sdpMid, Safari may fail to associate ICE candidates with the video stream, leading to incomplete connectivity.
Safari 11 has partial support for srcObject, and strict autoplay policies that can block video playback silently (appearing as a black screen). Update your onRemoteStreamAdded function to handle both cases:
function onRemoteStreamAdded(event) { const video = this.videoEl; // Handle srcObject with fallback for older Safari if ('srcObject' in video) { video.srcObject = event.stream; } else { // Fallback using deprecated API for Safari 11 compatibility video.src = URL.createObjectURL(event.stream); } // Explicitly trigger playback (Safari requires user interaction for autoplay) video.play().catch(err => { console.log('Play failed (likely due to autoplay restrictions):', err); // Suggest adding a user-initiated button to start playback if this happens }); }
Note: Safari 11 blocks autoplay without user interaction—make sure your WebRTC initialization is triggered by a user action (like a button click) instead of running on page load.
Your forceChosenVideoCodec function forces H264, but Safari 11 only supports specific H264 profiles (Baseline Profile, Level ≤ 3.1) with packetization mode 0. Check two things:
- Verify the Raspberry Pi is encoding H264 in Baseline Profile. Use
raspividflags like-pf baselineif you're configuring the camera directly. - Ensure your
forceChosenVideoCodecfunction modifies the SDP to set:profile-level-id=42e01f(Baseline Profile, Level 3.1)packetization-mode=0
Incorrect codec parameters will cause Safari to reject the media stream even if it supports H264.
Enable WebRTC debugging in Safari Developer Tools to get concrete error details:
- Open Safari Developer Tools → Console
- Check the "WebRTC" checkbox in the console filter bar
- Look for errors related to DTLS handshake, codec negotiation, or ICE connectivity—these will point directly to the root cause.
内容的提问来源于stack exchange,提问作者rkwan

