@flashphoner/websdk 2.0.201 → 2.0.206

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/docTemplate/README.md +1 -1
  2. package/examples/demo/sip/phone/phone.js +7 -10
  3. package/examples/demo/streaming/hls-player/hls-player.html +1 -4
  4. package/examples/demo/streaming/hls-player/hls-player.js +19 -1
  5. package/examples/demo/streaming/hls-player/player-page.html +1 -1
  6. package/examples/demo/streaming/hls-player/video-js.css +142 -51
  7. package/examples/demo/streaming/hls-player/video.js +27294 -20390
  8. package/examples/demo/streaming/hls-player/video.min.js +27 -0
  9. package/examples/demo/streaming/media_devices_manager/manager.js +27 -1
  10. package/examples/demo/streaming/media_devices_manager/media_device_manager.html +7 -0
  11. package/examples/typescript/two-way-streaming-ts/.gitignore +23 -0
  12. package/examples/typescript/two-way-streaming-ts/README.md +36 -0
  13. package/examples/typescript/two-way-streaming-ts/package.json +45 -0
  14. package/examples/typescript/two-way-streaming-ts/public/favicon.ico +0 -0
  15. package/examples/typescript/two-way-streaming-ts/public/index.html +33 -0
  16. package/examples/typescript/two-way-streaming-ts/public/logo192.png +0 -0
  17. package/examples/typescript/two-way-streaming-ts/public/logo512.png +0 -0
  18. package/examples/typescript/two-way-streaming-ts/public/manifest.json +25 -0
  19. package/examples/typescript/two-way-streaming-ts/public/media/preloader.mp4 +0 -0
  20. package/examples/typescript/two-way-streaming-ts/public/robots.txt +3 -0
  21. package/examples/typescript/two-way-streaming-ts/src/TwoWayStreamingApp.css +23 -0
  22. package/examples/typescript/two-way-streaming-ts/src/TwoWayStreamingApp.tsx +371 -0
  23. package/examples/typescript/two-way-streaming-ts/src/fp-utils.ts +117 -0
  24. package/examples/typescript/two-way-streaming-ts/src/index.css +13 -0
  25. package/examples/typescript/two-way-streaming-ts/src/index.tsx +9 -0
  26. package/examples/typescript/two-way-streaming-ts/tsconfig.json +26 -0
  27. package/examples/vue/two-way-streaming-vue/.gitignore +23 -0
  28. package/examples/vue/two-way-streaming-vue/README.md +36 -0
  29. package/examples/vue/two-way-streaming-vue/babel.config.js +5 -0
  30. package/examples/vue/two-way-streaming-vue/package.json +47 -0
  31. package/examples/vue/two-way-streaming-vue/public/favicon.ico +0 -0
  32. package/examples/vue/two-way-streaming-vue/public/index.html +17 -0
  33. package/examples/vue/two-way-streaming-vue/src/TwoWayStreamingApp.vue +346 -0
  34. package/examples/vue/two-way-streaming-vue/src/assets/media/preloader.mp4 +0 -0
  35. package/examples/vue/two-way-streaming-vue/src/fp-utils.js +117 -0
  36. package/examples/vue/two-way-streaming-vue/src/main.js +9 -0
  37. package/examples/vue/two-way-streaming-vue/vue.config.js +8 -0
  38. package/flashphoner-no-flash.js +4 -4
  39. package/flashphoner-no-flash.min.js +1 -1
  40. package/flashphoner-no-webrtc.js +4 -4
  41. package/flashphoner-no-webrtc.min.js +1 -1
  42. package/flashphoner-no-wsplayer.js +4 -4
  43. package/flashphoner-no-wsplayer.min.js +1 -1
  44. package/flashphoner-room-api.js +4 -4
  45. package/flashphoner-room-api.min.js +1 -1
  46. package/flashphoner-temasys-flash-websocket-without-adapterjs.js +4 -4
  47. package/flashphoner-temasys-flash-websocket.js +4 -4
  48. package/flashphoner-temasys-flash-websocket.min.js +1 -1
  49. package/flashphoner-webrtc-only.js +4 -4
  50. package/flashphoner-webrtc-only.min.js +1 -1
  51. package/flashphoner.js +4 -4
  52. package/flashphoner.min.js +1 -1
  53. package/package.json +2 -1
  54. package/src/constants.d.ts +1 -0
  55. package/src/flashphoner-core.d.ts +192 -0
  56. package/src/flashphoner-core.js +4 -4
  57. package/src/room-module.d.ts +29 -0
  58. package/examples/demo/streaming/hls-player/videojs-hls.min.js +0 -27
@@ -5,6 +5,7 @@ var STREAM_EVENT_TYPE = Flashphoner.constants.STREAM_EVENT_TYPE;
5
5
  var CONNECTION_QUALITY = Flashphoner.constants.CONNECTION_QUALITY;
6
6
  var MEDIA_DEVICE_KIND = Flashphoner.constants.MEDIA_DEVICE_KIND;
7
7
  var TRANSPORT_TYPE = Flashphoner.constants.TRANSPORT_TYPE;
8
+ var CONTENT_HINT_TYPE = Flashphoner.constants.CONTENT_HINT_TYPE;
8
9
  var CONNECTION_QUALITY_UPDATE_TIMEOUT_MS = 10000;
9
10
  var preloaderUrl = "../../dependencies/media/preloader.mp4";
10
11
  var Browser = Flashphoner.Browser;
@@ -412,6 +413,7 @@ function publish() {
412
413
  var mediaConnectionConstraints;
413
414
  var session = Flashphoner.getSessions()[0];
414
415
  var transportInput = $('#transportInput').val();
416
+ var contentHint = $('#contentHintInput').val();
415
417
  var cvo = $("#cvo").is(':checked');
416
418
  var strippedCodecs = $("#stripPublishCodecs").val();
417
419
 
@@ -434,7 +436,8 @@ function publish() {
434
436
  sdpHook: rewriteSdp,
435
437
  transport: transportInput,
436
438
  cvoExtension: cvo,
437
- stripCodecs: strippedCodecs
439
+ stripCodecs: strippedCodecs,
440
+ videoContentHint: contentHint
438
441
  }).on(STREAM_STATUS.PUBLISHING, function (stream) {
439
442
  $("#testBtn").prop('disabled', true);
440
443
  var video = document.getElementById(stream.id());
@@ -862,6 +865,29 @@ function readyControls() {
862
865
  option.value = transportType;
863
866
  transportOutput.appendChild(option);
864
867
  }
868
+
869
+ //init content hint form
870
+ var contentType;
871
+ var contentTypeValue;
872
+ var option;
873
+ var contentHintInput = document.getElementById("contentHintInput");
874
+ for (contentType in CONTENT_HINT_TYPE) {
875
+ option = document.createElement("option");
876
+ switch(contentType) {
877
+ case 'MOTION':
878
+ contentTypeValue = CONTENT_HINT_TYPE.MOTION;
879
+ break;
880
+ case 'DETAIL':
881
+ contentTypeValue = CONTENT_HINT_TYPE.DETAIL;
882
+ break;
883
+ case 'TEXT':
884
+ contentTypeValue = CONTENT_HINT_TYPE.TEXT;
885
+ break;
886
+ }
887
+ option.text = contentTypeValue;
888
+ option.value = contentTypeValue;
889
+ contentHintInput.appendChild(option);
890
+ }
865
891
  }
866
892
 
867
893
  // Stat
@@ -245,6 +245,13 @@
245
245
  <input type="checkbox" class="checkbox" id="cvo" value="false">
246
246
  </div>
247
247
  </div>
248
+ <div class="form-group" id="contentHintInputForm">
249
+ <label style="text-align: left" class="col-sm-4 control-label">Content Hint</label>
250
+ <div class="col-sm-6">
251
+ <select class="form-control" id="contentHintInput">
252
+ </select>
253
+ </div>
254
+ </div>
248
255
  <div class="form-group">
249
256
  <label style="text-align: left" class="col-sm-4 control-label">Mute</label>
250
257
  <div class="col-sm-6">
@@ -0,0 +1,23 @@
1
+ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2
+
3
+ # dependencies
4
+ /node_modules
5
+ /.pnp
6
+ .pnp.js
7
+
8
+ # testing
9
+ /coverage
10
+
11
+ # production
12
+ /build
13
+
14
+ # misc
15
+ .DS_Store
16
+ .env.local
17
+ .env.development.local
18
+ .env.test.local
19
+ .env.production.local
20
+
21
+ npm-debug.log*
22
+ yarn-debug.log*
23
+ yarn-error.log*
@@ -0,0 +1,36 @@
1
+ # Two Way Streaming React example application written in Typescript
2
+
3
+ This example shows how to integrate Flashphoner [WebCallServer](https://flashphoner.com) Javascript API ([WebSDK](https://www.npmjs.com/package/@flashphoner/websdk)) with Typescript typings to to React application
4
+
5
+ ## How to build
6
+
7
+ In the project directory, you can run:
8
+
9
+ ### `npm install`
10
+
11
+ Installs all the dependencies needed.
12
+
13
+ ### `npm start`
14
+
15
+ Runs the app in the development mode.\
16
+ Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
17
+
18
+ ### `npm run build`
19
+
20
+ Builds the app for production to the `build` folder.\
21
+ It correctly bundles React and WebSDK in production mode and optimizes the build for the best performance.
22
+
23
+ The build is minified and the filenames include the hashes.\
24
+ Your app is ready to be deployed!
25
+
26
+ ## How to deploy
27
+
28
+ Copy build folder content to a web server, for example
29
+ ```
30
+ mkdir -p /var/www/html/two-way-streaming-ts
31
+ cp -r build/* /var/www/html/two-way-streaming-ts
32
+ ```
33
+
34
+ Then you can open example page in browser `https://yourhost/two-way-streaming-ts/index.html`
35
+
36
+ Please note that you should open page via secure connection in browser for WebRTC to work, except localhost.
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "two-way-streaming-ts",
3
+ "description": "Two Way Streaming React appliction example written in Typescript using Flashphoner Web SDK",
4
+ "author": "Flashphoner",
5
+ "license": "MIT",
6
+ "version": "1.0.0",
7
+ "homepage": ".",
8
+ "private": true,
9
+ "dependencies": {
10
+ "@flashphoner/websdk": "^2.0.202",
11
+ "@types/jest": "^27.0.2",
12
+ "@types/node": "^16.10.3",
13
+ "@types/react": "^17.0.27",
14
+ "@types/react-dom": "^17.0.9",
15
+ "bootstrap": "^5.1.1",
16
+ "react": "^17.0.2",
17
+ "react-dom": "^17.0.2",
18
+ "react-scripts": "4.0.3",
19
+ "typescript": "^4.4.3"
20
+ },
21
+ "scripts": {
22
+ "start": "react-scripts start",
23
+ "build": "react-scripts build",
24
+ "test": "react-scripts test",
25
+ "eject": "react-scripts eject"
26
+ },
27
+ "eslintConfig": {
28
+ "extends": [
29
+ "react-app",
30
+ "react-app/jest"
31
+ ]
32
+ },
33
+ "browserslist": {
34
+ "production": [
35
+ ">0.2%",
36
+ "not dead",
37
+ "not op_mini all"
38
+ ],
39
+ "development": [
40
+ "last 1 chrome version",
41
+ "last 1 firefox version",
42
+ "last 1 safari version"
43
+ ]
44
+ }
45
+ }
@@ -0,0 +1,33 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ <meta name="theme-color" content="#000000" />
8
+ <meta
9
+ name="description"
10
+ content="Two Way Streaming example created using create-react-app"
11
+ />
12
+ <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
13
+ <!--
14
+ manifest.json provides metadata used when your web app is installed on a
15
+ user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
16
+ -->
17
+ <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
18
+ <!--
19
+ Notice the use of %PUBLIC_URL% in the tags above.
20
+ It will be replaced with the URL of the `public` folder during the build.
21
+ Only files inside the `public` folder can be referenced from the HTML.
22
+
23
+ Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
24
+ work correctly both with client-side routing and a non-root public URL.
25
+ Learn how to configure a non-root public URL by running `npm run build`.
26
+ -->
27
+ <title>TwoWay Streaming React App</title>
28
+ </head>
29
+ <body>
30
+ <noscript>You need to enable JavaScript to run this app.</noscript>
31
+ <div id="root"></div>
32
+ </body>
33
+ </html>
@@ -0,0 +1,25 @@
1
+ {
2
+ "short_name": "Two Way Streaming",
3
+ "name": "Two Way Streaming React App Sample",
4
+ "icons": [
5
+ {
6
+ "src": "favicon.ico",
7
+ "sizes": "64x64 32x32 24x24 16x16",
8
+ "type": "image/x-icon"
9
+ },
10
+ {
11
+ "src": "logo192.png",
12
+ "type": "image/png",
13
+ "sizes": "192x192"
14
+ },
15
+ {
16
+ "src": "logo512.png",
17
+ "type": "image/png",
18
+ "sizes": "512x512"
19
+ }
20
+ ],
21
+ "start_url": ".",
22
+ "display": "standalone",
23
+ "theme_color": "#000000",
24
+ "background_color": "#ffffff"
25
+ }
@@ -0,0 +1,3 @@
1
+ # https://www.robotstxt.org/robotstxt.html
2
+ User-agent: *
3
+ Disallow:
@@ -0,0 +1,23 @@
1
+ .fp-Video {
2
+ border: 1px double black;
3
+ width: 322px;
4
+ height: 242px;
5
+ text-align: center;
6
+ background: #c0c0c0;
7
+ margin: 0 auto 0 auto;
8
+ }
9
+
10
+ .display {
11
+ width: 100%;
12
+ height: 100%;
13
+ display: inline-block;
14
+ }
15
+
16
+ .display > video, object {
17
+ width: 100%;
18
+ height: 100%;
19
+ }
20
+
21
+ video:-webkit-full-screen {
22
+ border-radius: 1px;
23
+ }
@@ -0,0 +1,371 @@
1
+ import React, { Component } from 'react';
2
+ import './TwoWayStreamingApp.css';
3
+ import 'bootstrap/dist/css/bootstrap.min.css';
4
+ import * as FPUtils from './fp-utils';
5
+ import * as Flashphoner from '@flashphoner/websdk';
6
+
7
+ const SESSION_STATUS = Flashphoner.constants.SESSION_STATUS;
8
+ const STREAM_STATUS = Flashphoner.constants.STREAM_STATUS;
9
+ const Browser = Flashphoner.Browser;
10
+ const PRELOADER_URL = process.env.PUBLIC_URL + '/media/preloader.mp4';
11
+
12
+ interface TwoWayStreamingState {
13
+ apiFailed: string,
14
+ session: any,
15
+ sessionStatus: string,
16
+ sessionStatusClass: string,
17
+ localVideo: any,
18
+ remoteVideo: any,
19
+ publishStream: any,
20
+ publishStatus: string,
21
+ publishStatusClass: string,
22
+ playStream: any,
23
+ playStatus: string,
24
+ playStatusClass: string,
25
+ publishStreamName: string,
26
+ publishStreamNameDisabled: boolean,
27
+ playStreamName: string,
28
+ playStreamNameDisabled: boolean,
29
+ connectButtonText: string,
30
+ connectButtonDisabled: boolean,
31
+ serverUrl: string,
32
+ serverUrlDisabled: boolean,
33
+ publishButtonText: string,
34
+ publishButtonDisabled: boolean,
35
+ playButtonText: string,
36
+ playButtonDisabled: boolean
37
+ }
38
+
39
+ class TwoWayStreamingApp extends Component<{}, TwoWayStreamingState> {
40
+ constructor(props: any) {
41
+ super(props);
42
+ this.state = {
43
+ apiFailed: '',
44
+ session: null,
45
+ sessionStatus: '',
46
+ sessionStatusClass: 'text-muted',
47
+ localVideo: null,
48
+ remoteVideo: null,
49
+ publishStream: null,
50
+ publishStatus: '',
51
+ publishStatusClass: 'text-muted',
52
+ playStream: null,
53
+ playStatus: '',
54
+ playStatusClass: 'text-muted',
55
+ publishStreamName: 'streamName',
56
+ publishStreamNameDisabled: true,
57
+ playStreamName: 'streamName',
58
+ playStreamNameDisabled: true,
59
+ connectButtonText: 'Connect',
60
+ connectButtonDisabled: false,
61
+ serverUrl: 'wss://demo.flashphoner.com:8443',
62
+ serverUrlDisabled: false,
63
+ publishButtonText: 'Publish',
64
+ publishButtonDisabled: true,
65
+ playButtonText: 'Play',
66
+ playButtonDisabled: true
67
+ };
68
+ }
69
+
70
+ componentDidMount() {
71
+ try {
72
+ Flashphoner.init({});
73
+ this.setState({
74
+ localVideo: document.getElementById('localVideo'),
75
+ remoteVideo: document.getElementById('remoteVideo')
76
+ });
77
+ }
78
+ catch(e) {
79
+ console.log(e);
80
+ this.setState({
81
+ apiFailed: 'Your browser does not support WebRTC technology needed for this example',
82
+ connectButtonDisabled: true,
83
+ serverUrlDisabled: true
84
+ });
85
+ }
86
+ }
87
+
88
+ onConnected = (session: any) => {
89
+ this.setState({
90
+ session: session,
91
+ connectButtonText: 'Disconnect',
92
+ connectButtonDisabled: false,
93
+ serverUrlDisabled: true
94
+ });
95
+ this.onUnpublished();
96
+ this.onStopped();
97
+ }
98
+
99
+ onDisconnected = () => {
100
+ this.setState({
101
+ session: null,
102
+ connectButtonText: 'Connect',
103
+ connectButtonDisabled: false,
104
+ serverUrlDisabled: false
105
+ });
106
+ this.onUnpublished();
107
+ this.onStopped();
108
+ }
109
+
110
+ onPublishing = (stream: any) => {
111
+ this.setState({
112
+ publishStream: stream,
113
+ publishButtonText: 'Unpublish',
114
+ publishButtonDisabled: false
115
+ });
116
+ }
117
+
118
+ onUnpublished = () => {
119
+ let session = this.state.session;
120
+ let itemState = true;
121
+
122
+ if(session && session.status() === SESSION_STATUS.ESTABLISHED) {
123
+ itemState = false;
124
+ }
125
+ this.setState({
126
+ publishStream: null,
127
+ publishButtonText: 'Publish',
128
+ publishButtonDisabled: itemState,
129
+ publishStreamNameDisabled: itemState
130
+ });
131
+ }
132
+
133
+ onPlaying = (stream: any) => {
134
+ this.setState({
135
+ playStream: stream,
136
+ playButtonText: 'Stop',
137
+ playButtonDisabled: false
138
+ });
139
+ }
140
+
141
+ onStopped = () => {
142
+ let session = this.state.session;
143
+ let itemState = true;
144
+
145
+ if(session && session.status() === SESSION_STATUS.ESTABLISHED) {
146
+ itemState = false;
147
+ }
148
+ this.setState({
149
+ playStream: null,
150
+ playButtonText: 'Play',
151
+ playButtonDisabled: itemState,
152
+ playStreamNameDisabled: itemState
153
+ });
154
+ }
155
+
156
+ publishStream = () => {
157
+ let app = this;
158
+ let session = this.state.session;
159
+ let streamName = this.state.publishStreamName;
160
+ let localVideo = this.state.localVideo;
161
+
162
+ if(session && localVideo) {
163
+ session.createStream({
164
+ name: streamName,
165
+ display: localVideo,
166
+ cacheLocalResources: true,
167
+ receiveVideo: false,
168
+ receiveAudio: false
169
+ }).on(STREAM_STATUS.PUBLISHING, (stream: any) => {
170
+ app.setState({publishStatus: STREAM_STATUS.PUBLISHING, publishStatusClass: 'text-success'});
171
+ app.onPublishing(stream);
172
+ }).on(STREAM_STATUS.UNPUBLISHED, () => {
173
+ app.setState({publishStatus: STREAM_STATUS.UNPUBLISHED, publishStatusClass: 'text-success'});
174
+ app.onUnpublished();
175
+ }).on(STREAM_STATUS.FAILED, () => {
176
+ app.setState({publishStatus: STREAM_STATUS.FAILED, publishStatusClass: 'text-danger'});
177
+ app.onUnpublished();
178
+ }).publish();
179
+ }
180
+ }
181
+
182
+ playStream = () => {
183
+ let app = this;
184
+ let session = this.state.session;
185
+ let streamName = this.state.playStreamName;
186
+ let remoteVideo = this.state.remoteVideo;
187
+
188
+ if(session && remoteVideo) {
189
+ session.createStream({
190
+ name: streamName,
191
+ display: remoteVideo
192
+ }).on(STREAM_STATUS.PENDING, (stream: any) => {
193
+ let video: any = document.getElementById(stream.id());
194
+ if (!video.hasListeners) {
195
+ video.hasListeners = true;
196
+ video.addEventListener('resize', (event: any) => {
197
+ FPUtils.resizeVideo(event.target);
198
+ });
199
+ }
200
+ }).on(STREAM_STATUS.PLAYING, (stream: any) => {
201
+ app.setState({playStatus: STREAM_STATUS.PLAYING, playStatusClass: 'text-success'});
202
+ app.onPlaying(stream);
203
+ }).on(STREAM_STATUS.STOPPED, () => {
204
+ app.setState({playStatus: STREAM_STATUS.STOPPED, playStatusClass: 'text-success'});
205
+ app.onStopped();
206
+ }).on(STREAM_STATUS.FAILED, () => {
207
+ app.setState({playStatus: STREAM_STATUS.FAILED, playStatusClass: 'text-danger'});
208
+ app.onStopped();
209
+ }).play();
210
+ }
211
+ }
212
+
213
+ onConnectClick = () => {
214
+ let app = this;
215
+ let url = this.state.serverUrl;
216
+ let session = this.state.session;
217
+
218
+ if (!session) {
219
+ console.log("Create new session with url " + url);
220
+ app.setState({connectButtonDisabled: true, serverUrlDisabled: true});
221
+ Flashphoner.createSession({urlServer: url}).on(SESSION_STATUS.ESTABLISHED, (session: any) => {
222
+ app.setState({sessionStatus: SESSION_STATUS.ESTABLISHED, sessionStatusClass: 'text-success'});
223
+ app.onConnected(session);
224
+ }).on(SESSION_STATUS.DISCONNECTED, () => {
225
+ app.setState({sessionStatus: SESSION_STATUS.DISCONNECTED, sessionStatusClass: 'text-success'});
226
+ app.onDisconnected();
227
+ }).on(SESSION_STATUS.FAILED, () => {
228
+ app.setState({sessionStatus: SESSION_STATUS.FAILED, sessionStatusClass: 'text-danger'});
229
+ app.onDisconnected();
230
+ });
231
+ } else {
232
+ app.setState({connectButtonDisabled: true});
233
+ session.disconnect();
234
+ }
235
+ }
236
+
237
+ onPublishClick = () => {
238
+ let app = this;
239
+ let stream = this.state.publishStream;
240
+ let localVideo = this.state.localVideo;
241
+
242
+ if (!localVideo) return;
243
+ if (!stream) {
244
+ app.setState({publishButtonDisabled: true, publishStreamNameDisabled: true});
245
+ if (Browser.isSafariWebRTC()) {
246
+ Flashphoner.playFirstVideo(localVideo, true, PRELOADER_URL).then(() => {
247
+ app.publishStream();
248
+ });
249
+ return;
250
+ }
251
+ app.publishStream();
252
+ } else {
253
+ app.setState({publishButtonDisabled: true});
254
+ stream.stop();
255
+ }
256
+ }
257
+
258
+ onPlayClick = () => {
259
+ let app = this;
260
+ let stream = this.state.playStream;
261
+ let remoteVideo = this.state.remoteVideo;
262
+
263
+ if (!remoteVideo) return;
264
+ if (!stream) {
265
+ app.setState({playButtonDisabled: true, playStreamNameDisabled: true});
266
+ if (Flashphoner.getMediaProviders()[0] === "WSPlayer") {
267
+ Flashphoner.playFirstSound();
268
+ } else if (Browser.isSafariWebRTC()) {
269
+ Flashphoner.playFirstVideo(remoteVideo, false, PRELOADER_URL).then(() => {
270
+ app.playStream();
271
+ });
272
+ return;
273
+ }
274
+ app.playStream();
275
+ } else {
276
+ app.setState({playButtonDisabled: true});
277
+ stream.stop();
278
+ }
279
+ }
280
+
281
+ render() {
282
+ return (
283
+ <div className="container">
284
+ <h2 className="text-danger">{this.state.apiFailed}</h2>
285
+ <div className="row">
286
+ <h2 className="text-center">Two-way Streaming in Typescript</h2>
287
+ </div>
288
+ <div className="row row-space">
289
+ <div className="col-sm-6">
290
+ <div className="text-center text-muted">Local</div>
291
+ <div className="fp-Video">
292
+ <div id="localVideo" className="display"></div>
293
+ </div>
294
+ <div className="input-group col-sm-5" style={{margin: '10px auto 0 auto'}}>
295
+ <input type="text"
296
+ className="form-control"
297
+ placeholder="Stream Name"
298
+ value={this.state.publishStreamName}
299
+ disabled={this.state.publishStreamNameDisabled}
300
+ onChange={(event) => this.setState({publishStreamName: event.target.value})}
301
+ />
302
+ <div className="input-group-btn">
303
+ <button
304
+ className="btn btn-outline-dark"
305
+ disabled={this.state.publishButtonDisabled}
306
+ onClick={() => this.onPublishClick()}>
307
+ {this.state.publishButtonText}
308
+ </button>
309
+ </div>
310
+ </div>
311
+ <div className="text-center" style={{marginTop: '20px'}}>
312
+ <div className={this.state.publishStatusClass}>{this.state.publishStatus}</div>
313
+ </div>
314
+ </div>
315
+ <div className="col-sm-6">
316
+ <div className="text-center text-muted">Remote</div>
317
+ <div className="fp-Video">
318
+ <div id="remoteVideo" className="display"></div>
319
+ </div>
320
+ <div className="input-group col-sm-5" style={{margin: '10px auto 0 auto'}}>
321
+ <input type="text"
322
+ className="form-control"
323
+ placeholder="Stream Name"
324
+ value={this.state.playStreamName}
325
+ disabled={this.state.playStreamNameDisabled}
326
+ onChange={(event) => this.setState({playStreamName: event.target.value})}
327
+ />
328
+ <div className="input-group-btn">
329
+ <button
330
+ className="btn btn-outline-dark"
331
+ disabled={this.state.playButtonDisabled}
332
+ onClick={() => this.onPlayClick()}>
333
+ {this.state.playButtonText}
334
+ </button>
335
+ </div>
336
+ </div>
337
+ <div className="text-center" style={{marginTop: '20px'}}>
338
+ <div className={this.state.playStatusClass}>{this.state.playStatus}</div>
339
+ </div>
340
+ </div>
341
+ </div>
342
+ <div className="row row-space">
343
+ <div className="col-sm-6 offset-sm-3">
344
+ <div className="input-group col-sm-5">
345
+ <input type="text"
346
+ className="form-control"
347
+ placeholder="Server Url"
348
+ value={this.state.serverUrl}
349
+ disabled={this.state.serverUrlDisabled}
350
+ onChange={(event) => this.setState({serverUrl: event.target.value})}
351
+ />
352
+ <div className="input-group-btn">
353
+ <button
354
+ className="btn btn-outline-dark"
355
+ disabled={this.state.connectButtonDisabled}
356
+ onClick={() => this.onConnectClick()}>
357
+ {this.state.connectButtonText}
358
+ </button>
359
+ </div>
360
+ </div>
361
+ <div className="text-center" style={{marginTop: '20px'}}>
362
+ <div className={this.state.sessionStatusClass}>{this.state.sessionStatus}</div>
363
+ </div>
364
+ </div>
365
+ </div>
366
+ </div>
367
+ );
368
+ };
369
+ }
370
+
371
+ export default TwoWayStreamingApp;