npm package: @feige0629/unity-render-streaming
Description: >本包只是React客户端，需要配合 定制的 webserver 服务端进行使用
Latest version: 0.1.26

# @feige0629/unity-render-streaming 使用
>本包只是React客户端，需要配合 定制的 webserver 服务端进行使用

#### Tips：需要React客户端源码+本客户端定制的服务端源码，可加微信，备注来意
> 微信：feige0629

# 说明
Unity Render Streaming是Unity官方推出的一套云渲染解决方案，可以实现将我们打包的.exe程序运行于服务器云端，在浏览器、移动端进行显示，该解决方案基于Google开发的WebRTC流技术，以及Unity官方推出的新的输入系统Input System来实现，主要用于三端通信，客户端(本React端为客户端)、服务器端、 unity.exe程序。

![渲染后示例图片](https://iili.io/HP66rbI.png)

### 1、安装

```js
npm install @feige0629/unity-render-streaming

yarn add @feige0629/unity-render-streaming
```

### 2、本包封装了2个React组件
```js
// 1、这是从 Unity 接收视频/音频的示例。可以结合BroadcastUnity Render Streaming的场景使用。
<Receiver websocketUrl= 'ws://127.0.0.1:7000' autoPlay={true} style={{width:600, height:400}} /> 
```
```js
// 2、这是一个示例，用于接收在 Unity 上渲染的相机图像。您可以通过浏览器在 Unity 中操作相机。可以结合WebBrowserInputUnity Render Streaming的场景使用。WebApp 必须在公共模式下运行。
<Videoplayer websocketUrl= 'ws://127.0.0.1:7000' autoPlay={true} style={{width:600, height:400}} /> 
```

### 3、Videoplayer Demo 使用方法
```js
import { useRef, useState } from 'react';
import '../App.css'
import { Videoplayer, VideoplayerRef } from '../webserver';

function VideoDemo() 
{
  const receiverRef = useRef<VideoplayerRef>(null);
  const [autoPlay, setAutoPlay] = useState<boolean>(true); //是否自动播放

  // 播放视频
  const playButton = ()=>{
    receiverRef.current!.playVideo();
    setAutoPlay(true);
  }

  // 加载完成
  const onComplate = (videoRef: HTMLVideoElement, videoPlayer: any) => {
    console.log('加载完成：',videoRef, videoPlayer);
  }
  
  return (
    <div id="container">
      <h1>VideoPlayer Sample</h1>
      <div id="video-container">
        <Videoplayer ref={receiverRef} websocketUrl= 'ws://127.0.0.1:5173/video' onComplate={onComplate} autoPlay={autoPlay} style={{width:600, height:400}} />
        {
          !autoPlay && 
          <div id="player">
            <button id="playButton" onClick={playButton}>播放</button>
          </div>
        }
      </div>
    </div>
  );
}

export default VideoDemo;
```

### 4、Receiver Demo 使用方法
```js
import { useRef, useState } from 'react';
import '../App.css'
import { Receiver, ReceiverRef } from '../webserver';

function ReceiverDemo() 
{
  const receiverRef = useRef<ReceiverRef>(null);
  const [autoPlay, setAutoPlay] = useState<boolean>(true); //是否自动播放
  const [show, setShow] = useState<boolean>(false);
  const [websocketUrl, setWebsocketUrl] = useState<string>('ws://127.0.0.1:5173/ws');

  // 播放视频
  const playButton = ()=>{
    receiverRef.current!.playVideo();
    setAutoPlay(true);
  }

  // 发送消息
  const sendMessageButton = ()=>{
    receiverRef.current!.sendMessage(JSON.stringify({"MessageType":"1", "Content":"测试数据"}));
  }
  
  // 监听消息
  const onMessage = (msg:MessageEvent) => {
    console.log(`Receive Msg：`, msg.data, msg);
  }

  // 加载完成
  const onComplate = (videoRef: HTMLVideoElement, videoPlayer: any, renderstreaming: any) => {
    setShow(true);
    console.log('加载完成：',videoRef, videoPlayer, renderstreaming);
  }

  // 结束链接
  const onDisconnect = ()=>{
    console.log('结束');
  }

  return (
    <div id="container">
      <h1>Receiver Sample - {show ? '加载成功' : '启动中...'}</h1>
      <div id="video-container">
        <Receiver ref={receiverRef} config={{
          iceServers : [
            {
              urls: ['turn:xxx.xxx.xx.xx:3478?transport=udp'],
              username: 'admin',
              credential: '123456'
            }
          ]
        }} onMessage={onMessage} websocketUrl={websocketUrl} onDisconnect={onDisconnect} onComplate={onComplate} autoPlay={autoPlay} style={{width:600, height:400}} />
        {
          !autoPlay && 
          <div id="player">
            <button id="playButton" onClick={playButton}>播放</button>
          </div>
        }
      </div>
      { autoPlay && <button id="sendButton" onClick={sendMessageButton}>发送数据</button> }
      <button id="sendButton" onClick={()=>setWebsocketUrl('ws://127.0.0.1:5173/ws')}>本地websocketUrl</button>
      <button id="sendButton" onClick={()=>setWebsocketUrl('ws://127.0.0.1:5173/fwq')}>服务器websocketUrl</button>
    </div>
  );
}

export default ReceiverDemo;
```

### 5、API
| 参数     | 说明     | 类型     | 默认值	     | 适用组件     |
| -------- | -------- | -------- | -------- | -------- |
| autoPlay | 自动播放 | boolean | true | Receiver, Videoplayer |
| style | 自定义样式 | CSSProperties | - | Receiver, Videoplayer |
| className | className属性 | string | - | Receiver, Videoplayer |
| config | 配置 | { logging?: string; startupMode?: string; useWebSocket?: boolean; sdpSemantics?: string; iceServers?: { [key:number]:{ urls: string[], username?: string, credential?: string } }[]; } | { logging: "dev", startupMode: "public", useWebSocket: true, sdpSemantics:'unified-pla', iceServers : [{ urls: ['stun:stun.l.google.com:19302'] }],username: 'admin', credential: '123456' } | Receiver, Videoplayer |
| websocketUrl | websocket协议地址, config.useWebSocket为true启用 | string | location.protocol === "https:" ? "wss://" + location.host : "ws://" + location.host | Receiver, Videoplayer |
| signalingOrigin | signaling协议地址, config.useWebSocket为false启用 | string | location.origin | Receiver, Videoplayer |
| onMessage | 监听服务器端消息 | (msg: MessageEvent) => void | - | Receiver |
| onStatsMessage | 监听video状态数据 | (msg: statsType[]) => void | - | Receiver |
| onComplate | 加载完成，renderstreaming只在Receiver组件返回 | (videoRef: HTMLVideoElement, videoPlayer: any, renderstreaming: any) => void | - | Receiver, Videoplayer |
| onDisconnect | 关闭回调 | - | - | Receiver, Videoplayer |

### 6、方法
| 名称     | 描述     | 适用组件     |
| -------- | -------- | -------- |
| sendMessage | 发送消息(message: string)  | Receiver |
| playVideo | 播放视频 | Receiver, Videoplayer |
| disconnect | 调用关闭 | Receiver, Videoplayer |

### 7、外网服务器部署
>对于大多数 WebRTC 应用，服务器都需要在对等设备之间中继流量，因为在客户端之间通常无法实现直接套接字(除非这些应用在同一个本地网络中)。解决此问题的常见方法是使用TURN 服务器。术语表示使用中继 NAT 的遍历，是一种中继网络流量的协议。

#### 参考Unity文档中TURN 服务器设置
https://docs.unity3d.com/Packages/com.unity.renderstreaming@3.1/manual/turnserver.html

#### TURN服务器使用的端口需要公开，可设置最大最小值
| 协议     | 端口     |
| -------- | -------- |
| TCP | 32355-65535、3478-3479  |
| UDP | 32355-65535、3478-3479 |