App.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import React from 'react';
  2. import sdk, { Client, User, Stream } from 'urtc-sdk';
  3. import styled from 'styled-components';
  4. import config from './config';
  5. import './App.css';
  6. const StreamComponent = styled.div`
  7. position: relative;
  8. width: 400px;
  9. height: 300px;
  10. text-align: left;
  11. `;
  12. const roomId = 'test';
  13. const userId = `${Math.random()}`;
  14. function useClient(appId: string, token: string): Client {
  15. const [client] = React.useState<Client>(() => {
  16. const client = new Client(appId, token);
  17. (window as any).c = client;
  18. return client;
  19. });
  20. return client;
  21. }
  22. function useRoomStatus(client: Client): {
  23. joined: boolean;
  24. join: Function;
  25. leave: Function;
  26. } {
  27. const [joined, setJoined] = React.useState<boolean>(false);
  28. function join(roomId: string, userId: string) {
  29. if (joined) return;
  30. client.joinRoom(roomId, userId, (users: User[], streams: Stream[]) => {
  31. console.log('demo - join ', users, streams);
  32. setJoined(true);
  33. }, (err: Error) => {
  34. console.error('demo - join ', err);
  35. });
  36. }
  37. function leave() {
  38. if (!joined) return;
  39. client.leaveRoom(undefined, (): void => {
  40. setJoined(false);
  41. console.log('离开房间');
  42. }, (err: Error): void => {
  43. console.error('离开房间 ', err);
  44. });
  45. }
  46. return { joined, join, leave };
  47. }
  48. function useLocalStream(client: Client, joined: boolean): Stream | undefined {
  49. const [stream, setStream] = React.useState<Stream>();
  50. React.useEffect(() => {
  51. if (joined) {
  52. // 加入房间立即推流
  53. client.publish({audio: true, video: true, screen: false}, (err: any) => {
  54. console.error('demo - publish ', err)
  55. });
  56. } else {
  57. setStream(undefined);
  58. }
  59. function handlePublished(stream: Stream): void {
  60. console.log('stream-published ', stream);
  61. setStream(stream);
  62. client.play({
  63. container: stream.sid,
  64. streamId: stream.sid,
  65. }, (err) => {
  66. if (err) {
  67. console.error('play publish stream ', err);
  68. }
  69. });
  70. }
  71. client.on('stream-published', handlePublished);
  72. return function() {
  73. client.off('stream-published', handlePublished);
  74. }
  75. }, [client, joined]);
  76. return stream;
  77. }
  78. function useRemoteStreams(client: Client, joined: boolean): Stream[] {
  79. const [remoteStreams, setRemoteStreams] = React.useState<Stream[]>([]);
  80. React.useEffect(() => {
  81. if (!joined) {
  82. setRemoteStreams([]);
  83. }
  84. function handleStreamAdded(stream: Stream): void {
  85. console.log('stream-added ', stream);
  86. client.subscribe(stream.sid, (err) => console.error('demo - subscribe ', err));
  87. // remoteStreams.push(stream);
  88. setRemoteStreams((preStreams: Stream[]): Stream[] => (preStreams.concat(stream)));
  89. }
  90. function handleSubscribed(stream: Stream): void {
  91. console.log('stream-subscribed ', stream);
  92. client.play({
  93. container: stream.sid,
  94. streamId: stream.sid,
  95. }, (err) => {
  96. if (err) {
  97. console.error('play subscribe stream ', err);
  98. }
  99. });
  100. }
  101. function handleStreamRemoved(stream: Stream): void {
  102. console.log('stream-removed ', stream);
  103. // client.subscribe(stream.sid, (err) => console.error('demo - subscribe ', err));
  104. setRemoteStreams((preStreams: Stream[]): Stream[] => (preStreams.filter((item) => item.sid !== stream.sid)));
  105. }
  106. client.on('stream-added', handleStreamAdded);
  107. client.on('stream-subscribed', handleSubscribed);
  108. client.on('stream-removed', handleStreamRemoved);
  109. return function() {
  110. client.off('stream-subscribed', handleSubscribed);
  111. client.off('stream-added', handleStreamAdded);
  112. client.off('stream-removed', handleStreamRemoved);
  113. }
  114. }, [client, joined]);
  115. return remoteStreams;
  116. }
  117. function URTC() {
  118. console.log('demo - start', sdk.version);
  119. const token = sdk.generateToken(config.AppId, config.AppKey, roomId, userId);
  120. const client = useClient(config.AppId, token);
  121. const { joined, join, leave } = useRoomStatus(client);
  122. const stream = useLocalStream(client, joined);
  123. const remoteStreams = useRemoteStreams(client, joined);
  124. return (
  125. <div>
  126. <label>
  127. 房间号:{roomId}({joined ? "已加入" : "未加入"})
  128. {joined ? <button onClick={() => leave()}>离开</button> : <button onClick={() => join(roomId, userId)}>加入</button> }
  129. </label>
  130. <h5>本地流</h5>
  131. {
  132. stream
  133. ? <StreamComponent className="stream" id={stream.sid}></StreamComponent>
  134. : null
  135. }
  136. <h5>远端流</h5>
  137. {remoteStreams.map(stream => <StreamComponent className="stream" key={stream.sid} id={stream.sid}></StreamComponent>)}
  138. </div>
  139. )
  140. }
  141. function App() {
  142. return (
  143. <div className="App">
  144. <header className="App-header">
  145. <URTC></URTC>
  146. </header>
  147. </div>
  148. );
  149. }
  150. export default App;