Google Nest Cam电池版WebRTC直播流iPhone端无法播放问题求助
解决iPhone端Google Nest Cam Battery WebRTC直播流无法播放问题
我通过WebRTC协议获取新款Google Nest Cam Battery摄像头的直播流,该流在Android设备和PC端均可正常播放,但iPhone端无法正常工作。我尝试用RTCPeerConnection结合Simplepeer实现,仍未解决问题。
以下是我使用的代码:
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> <title>Camera - T-Construction</title> </head> <body style="background-color: #D3D3D3;"> <center><br><br><h2 style="color: black;">Voici la vue en direct de votre construction</h2><br><br> <video id="webCamVideo" controls autoplay playsinline loop width="80%" /></center><br> <?php $client_id = 'CLIENTID'; $client_secret = 'CLIENTSECRET'; $project_id = 'PROJECTID'; $refresh_token = 'REFRESHTOKEN'; require 'dbcon.php'; $ids = 1; $devicestat = $con -> prepare("select deviceid from clients where id = ?"); $devicestat -> bindParam(1, $ids); $devicestat -> execute(); $devicedon = $devicestat -> fetchall(); $deviceid = $devicedon[0]["deviceid"]; $auth_url = "https://www.googleapis.com/oauth2/v4/token"; $auth_data = array( 'client_id' => $client_id, 'client_secret' => $client_secret, 'refresh_token' => $refresh_token, 'grant_type' => 'refresh_token' ); $auth_curl = curl_init($auth_url); curl_setopt($auth_curl, CURLOPT_POST, true); curl_setopt($auth_curl, CURLOPT_POSTFIELDS, http_build_query($auth_data)); curl_setopt($auth_curl, CURLOPT_RETURNTRANSFER, true); $auth_response = curl_exec($auth_curl); curl_close($auth_curl); $auth_data = json_decode($auth_response, true); //i get the access token for get the stream after if (isset($auth_data['access_token'])) { $access_token = $auth_data['access_token']; $_COOKIE["acto"] = $access_token; } ?> <script src="simplepeer.min.js"></script> <script type="text/javascript"> const configuration = { iceServers: [ { urls: [ 'stun:stun1.l.google.com:19302', 'stun:stun2.l.google.com:19302', ], }, ], iceCandidatePoolSize: 10, }; let peerConnection = null; let remoteStream = null; async function startFeed() { peerConnection = new RTCPeerConnection(configuration); const token = '<?php echo($_COOKIE["acto"]); ?>'; const projectid = "<?php echo($project_id); ?>"; const deviceid = "<?php echo($deviceid); ?>"; remoteStream = new MediaStream(); const videoElement = document.querySelector('#webCamVideo'); if (videoElement) { videoElement.srcObject = remoteStream; } // Watch for new tracks from remote stream; add to video stream peerConnection.ontrack = event => { event.streams[0].getTracks().forEach(track => { remoteStream.addTrack(track); }); }; // Data Channel Required by the SDM API. if (peerConnection.createDataChannel) { peerConnection.createDataChannel("dataSendChannel"); } try { // Create the offer. const offer = await peerConnection.createOffer({ offerToReceiveAudio: true, offerToReceiveVideo: true }); await peerConnection.setLocalDescription(offer); // Safari doesn't respect the parameter requests of createOffer above, so let's fudge the offer ourselves! I mnot sure how to do let offerSdp = offer.sdp; offerSdp = offerSdp.replace('a=sendrecv', 'a=recvonly'); // Now, send request for SDP connection const url = "https://smartdevicemanagement.googleapis.com/v1/enterprises/" + projectid + "/devices/" + deviceid + ":executeCommand"; const options = { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token }, body: JSON.stringify({ "command": "sdm.devices.commands.CameraLiveStream.GenerateWebRtcStream", "params": { "offerSdp": offerSdp } }) }; const response = await fetch(url, options); // Process the response. const data = await response.json(); let answerSdp = data.results.answerSdp; // Now start the feed using the answer const answer = new RTCSessionDescription({ type: 'answer', sdp: answerSdp }); await peerConnection.setRemoteDescription(answer); } catch (error) { console.error("Error starting feed:", error); } } // Call startFeed when the page is loaded. window.addEventListener('load', startFeed); </script> <button onclick="startVideo()">Démarrer la vidéo</button> <script> function startVideo(){ let canvas = document.createElement('canvas'); let video = document.getElementById('webCamVideo'); canvas.width = 768; canvas.height = 432; let ctx = canvas.getContext('2d'); ctx.drawImage( video, 0, 0, canvas.width, canvas.height ); var image = new Image(); image.src = canvas.toDataURL('image/jpeg'); // Convertir le canvas en format d'image document.body.appendChild(image); } </script> </body> </html>
针对性解决建议
- 修复Safari的SDP全局替换:原代码仅替换单个
a=sendrecv条目,Safari生成的SDP可能包含多个该字段,改用正则全局替换:offerSdp = offerSdp.replace(/a=sendrecv/g, 'a=recvonly'); - 适配Safari视频自动播放规则:iPhone Safari对自动播放有严格限制,给视频标签添加
muted属性(即使不需要音频):<video id="webCamVideo" controls autoplay playsinline loop muted width="80%" /> - 补充TURN服务器配置:仅STUN服务器可能无法穿透复杂NAT环境,添加TURN服务器提升兼容性:
const configuration = { iceServers: [ { urls: ['stun:stun1.l.google.com:19302', 'stun:stun2.l.google.com:19302'] }, { urls: 'turn:turn.example.com:3478', username: 'your-username', credential: 'your-credential' } ], iceCandidatePoolSize: 10, }; - 增强错误排查日志:在
catch块中添加响应状态和文本输出,便于定位问题:catch (error) { console.error("Error starting feed:", error); if (response) { response.text().then(text => console.error("Response details:", response.status, text)); } } - 调整数据通道创建时机:SDM API要求的数据通道,建议在
setLocalDescription完成后创建,避免Safari初始化异常:await peerConnection.setLocalDescription(offer); // 移到此处创建数据通道 if (peerConnection.createDataChannel) { peerConnection.createDataChannel("dataSendChannel"); }
内容的提问来源于stack exchange,提问作者Eren TURKOGLU
相关产品推荐
相关产品推荐

