You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 05:34:55