[{"data":1,"prerenderedAt":70},["ShallowReactive",2],{"code-python-1gaeu92":3,"code-ts-1wmni4h":4,"code-swift-1f3tl":5,"code-kotlin-1x9e72h":6,"code-cpp-4wg9l1":7,"code-python-11oqx6y":8,"$fEvdkNwDonu5Lu_09CUYEvqzubi3Tt24HKwrVXFSuYNk":9},"\u003Cpre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\"># 服务端：pip install \"srtc[pipecat]\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> srtc.pipecat_transport \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> SRTCParams, SRTCTransport\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">transport \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> SRTCTransport(token, SRTCParams(\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFAB70\">    audio_in_enabled\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">True\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"color:#FFAB70\">audio_out_enabled\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">True\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">))\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">pipeline \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> Pipeline([\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">    transport.input(), stt, llm, tts,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">    transport.output(),\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">])\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>","\u003Cpre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> { SRTC, CameraPresets, MicPresets } \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\"> '@seastart\u002Fsrtc-web-sdk'\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 初始化\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\"> srtc\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> new\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\"> SRTC\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 加入频道\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\"> channel\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> srtc.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">join\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(token)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 订阅远端混音（收听远端声音）\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\"> remoteAudio\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> srtc.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">subscribeRemoteAudioMixTrack\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> remoteAudio.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">startPlay\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 打开麦克风\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\"> micTrack\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> srtc.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">createLocalMicTrack\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(MicPresets.music)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> micTrack.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">startCapture\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> srtc.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">publishLocalTrack\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(micTrack)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 打开摄像头并预览\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\"> cameraTrack\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> srtc.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">createLocalCameraTrack\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(CameraPresets[\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">'720p'\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">])\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> cameraTrack.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">startCapture\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">cameraTrack.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">addPlayView\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(document.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">querySelector\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">'#local-video'\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">)\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">!\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> srtc.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">publishLocalTrack\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(cameraTrack)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 离开频道\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> srtc.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">leave\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>","\u003Cpre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\"> SRTC\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">let\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> srtc \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\"> SRTC\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 加入频道\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">let\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> channel \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> try\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> srtc.\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">joinChannel\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">    token\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: token,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">    options\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">JoinOptions\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">autoSubscribeAudio\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">true\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 打开麦克风\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">let\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> micTrack \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> srtc.\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">createLocalMicTrack\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">preset\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: .music)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">try\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> micTrack.\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">startCapture\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">try\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> channel.\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">publishLocalTrack\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(micTrack)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 打开摄像头\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">let\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> cameraTrack \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> srtc.\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">createLocalCameraTrack\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">preset\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: .h720p)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">try\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> cameraTrack.\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">startCapture\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">try\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> channel.\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">publishLocalTrack\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(cameraTrack)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 订阅远端视频（通过 ChannelDelegate 回调）\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\"> channel\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">_\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> channel: Channel, \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">user\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: UserInfo, \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">didAddTrack\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> track: TrackInfo) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    guard\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> track.kind \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">==\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> .video \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">else\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> { \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">return\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    try?\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> channel.\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">subscribeRemoteVideoTrack\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">uid\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: user.uid, \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">trackId\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: track.id)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 离开频道\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> srtc.\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">leaveChannel\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>","\u003Cpre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 初始化引擎\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">val\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> rtcEngine \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> RTCEngine.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">create\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(app \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> application, enableLocalLog \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\"> true\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">rtcEngine.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">initSDK\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 绑定回调\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">rtcEngine.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">setRtcClientEvent\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">object\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> : \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">RTCClientEvent\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    override\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> fun\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\"> onJoinSucceed\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(channel: \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">String\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">, uid: \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">String\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">, whiteBoard: \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">String\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">?) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">        \u002F\u002F 加入频道成功\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">    }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    override\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> fun\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\"> onStreamTrackAdd\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(uid: \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">String\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">, channel: \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">String\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">, trackId: \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">String\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">, trackDesc: \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">String\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">        \u002F\u002F 收到远端码流，在这里订阅远端视频\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">        val\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> remoteTrack \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> rtcEngine.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">getRemoteVideoTrack\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(uid, trackDesc)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">        remoteTrack?.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">addPlayView\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(remoteView)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">        rtcEngine.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">subscribeRemoteTrack\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(uid, trackId, \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">null\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">    }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">})\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 加入频道\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">val\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> joinOptions \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\"> JoinOptions\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(autoSubscribeAudio \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\"> true\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">, autoSubscribeVideo \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\"> true\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">rtcEngine.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">join\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(activity \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\"> this\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">, token \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> token, options \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> joinOptions, resultListener \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\"> null\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 打开摄像头\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">val\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> cameraTrack \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> rtcEngine.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">getLocalCameraTrack\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(PreOptionCamera._720P)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">cameraTrack.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">addPlayView\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(previewView)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">cameraTrack.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">startCapture\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> { rtcEngine.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">publishLocalVideo\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(track \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> cameraTrack, \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">..\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">.) }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 打开麦克风\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">val\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> micTrack \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> rtcEngine.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">getLocalMicTrack\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(PreOptionMic.def)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">rtcEngine.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">publishLocalAudio\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(track \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> micTrack, \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">..\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">.)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 离开频道并释放资源\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">rtcEngine.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">leave\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">rtcEngine.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">releaseSDK\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>","\u003Cpre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 初始化 SDK\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">SRTC\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">::IRTCEngine\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">*\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> _irtc \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\"> nullptr\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">SRTC\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">::\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">RTCEngine_Init\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">&#x26;\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">_irtc);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">_irtc->\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">setEventHandler\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">this\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 加入频道\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">std\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">::string token \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\"> \"从服务端获取的 token\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">_irtc->\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">joinChannel\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(token);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 打开摄像头\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">SRTC\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">::IRTCLocalCameraTrack\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">*\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> camTrack \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\"> nullptr\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">_irtc->\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">getCameraTrack\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"camera\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">&#x26;\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">camTrack);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">camTrack->\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">addPlayView\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(previewView);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">camTrack->\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">startCapture\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">();\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">_irtc->\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">publish\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(camTrack);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 打开麦克风\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">SRTC\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">::IRTCLocalMicTrack\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">*\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> micTrack \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\"> nullptr\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">_irtc->\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">getAudioTrack\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"mic\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">&#x26;\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">micTrack);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">micTrack->\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">startCapture\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">();\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">_irtc->\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">publish\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(micTrack);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 订阅远端视频（在 onStreamTrackAdd 回调中）\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">SRTC\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">::IRTCRemoteVideoTrack\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">*\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> remoteTrack \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\"> nullptr\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">_irtc->\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">getRemoteVideoTrack\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(uid, trackId, \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">&#x26;\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">remoteTrack);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">remoteTrack->\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">addPlayView\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(hwnd);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">_irtc->\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">subscribe\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(remoteTrack);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">\u002F\u002F 离开频道\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">_irtc->\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">leaveChannel\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">();\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>","\u003Cpre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> asyncio\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> srtc\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">async\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> def\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\"> main\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(token: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">str\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">):\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">    # 加入频道，自动订阅频道内所有人的音频（上下文管理器退出时自动离开）\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    async\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> with\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> srtc.Channel.join(token, \u003C\u002Fspan>\u003Cspan style=\"color:#FFAB70\">auto_subscribe_audio\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">True\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">) \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">as\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> ch:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">        print\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"已加入频道:\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">, ch.info.channel)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">        # 发布一路音频：write() 接收任意采样率的 PCM，SDK 按实时节奏发送\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">        tts \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> ch.publish_audio(\u003C\u002Fspan>\u003Cspan style=\"color:#FFAB70\">desc\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"tts\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"color:#FFAB70\">audio_format\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">srtc.AudioFormat(\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">24000\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">1\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">))\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">        # 逐帧消费远端音频（16k 单声道 PCM，按 uid 区分说话人）\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">        async\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> for\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> frame \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">in\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> ch.audio_frames():\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">            text \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> asr.transcribe(frame.pcm)       \u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\"># 接你的 ASR\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">            if\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> text:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">                await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> tts.write(\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> llm_tts(text))     \u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\"># LLM + TTS 的结果直接播回频道\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">asyncio.run(main(\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"&#x3C;服务端签发的 token>\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">))\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[10,27,43,55],{"slug":11,"sourceSlug":12,"title":13,"description":14,"date":15,"cover":16,"tags":17,"column":26},"261028-ai","261028-电话接入实时语音AI","电话客服想接 AI，要不要换线路、换系统？用现有 SIP 线路接入实时语音 AI 的落地方案与实测","企业热线、预约、回访仍以电话为主，接 AI 时最担心换线路、改呼叫中心、数据出网。本文介绍 STMLink SAI Agent 用运营商 SIP Trunk 或已有 IP-PBX 直接接入实时语音 AI 的三种接法、关键设计与实测数据：接听后约 0.3 秒开口，按键约 4 毫秒送达 AI，支持全离线部署。","2026-10-28","\u002Finsights\u002F261028-ai\u002Fcover.png",[18,19,20,21,22,23,24,25],"电话AI","AI客服","SIP Trunk","IP-PBX","实时语音AI","私有化部署","STMLink","SAI Agent","行业方案",{"slug":28,"sourceSlug":29,"title":30,"description":31,"date":32,"cover":33,"tags":34,"column":42},"260927-legacy-devices-rtc-ai","260927-传统设备利旧接入信创RTC与AI引擎","老旧会议系统改造实务：SIP\u002FH.323\u002FGB28181 监控与会议设备，如何平滑接入信创 RTC 与 AI 对话引擎？","面向政企、央国企与金融机构视讯架构师及数字化负责人，深入剖析传统硬件视频终端与安防监控利旧改造的三大技术断层，提供兼顾信创国产化平替与 AI 对话引擎低延迟集成的融合架构方案与选型对比指南。","2026-09-27","\u002Finsights\u002F260927-legacy-devices-rtc-ai\u002Fcover.png",[35,36,37,38,39,40,41,24],"传统设备利旧","SIP协议","H.323","GB28181","信创RTC","实时音视频","AI实时对话","传统设备融合",{"slug":44,"sourceSlug":45,"title":46,"description":47,"date":48,"cover":49,"tags":50,"column":54},"260924","260924-政企音视频选型","政企音视频系统选型：公有云 RTC、开源架构还是商业私有化 SDK？","面向政企、金融与央国企数字化决策者，深度剖析音视频通信系统的三大硬性约束（专网控流、合规存证、信创与设备利旧），提供公有云、开源自建与私有化 SDK 的全景选型决策指南。","2026-09-24","\u002Finsights\u002F260924\u002Fcover.png",[40,51,23,52,53,24],"RTC选型","信创国产化","视频会议","选型对比",{"slug":56,"sourceSlug":57,"title":58,"description":59,"date":60,"cover":61,"tags":62,"column":69},"260608","260608-高考零容错实时系统","不允许失败的实时系统，到底难在哪几层？——从高考的工程视角，看企业级实时音视频选型","给要做在线考试、远程庭审、远程会诊、应急指挥这类'不能出错'实时音视频系统的技术决策者：高考这套零容错巨型系统，把企业级 RTC 真正的工程约束放大了出来。","2026-06-08","\u002Finsights\u002F260608\u002Fcover.png",[40,63,23,64,65,66,67,68],"RTC","弱网对抗","高并发","信创","在线考试","远程庭审","技术解析",1793700842479]