@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.
- package/docTemplate/README.md +1 -1
- package/examples/demo/sip/phone/phone.js +7 -10
- package/examples/demo/streaming/hls-player/hls-player.html +1 -4
- package/examples/demo/streaming/hls-player/hls-player.js +19 -1
- package/examples/demo/streaming/hls-player/player-page.html +1 -1
- package/examples/demo/streaming/hls-player/video-js.css +142 -51
- package/examples/demo/streaming/hls-player/video.js +27294 -20390
- package/examples/demo/streaming/hls-player/video.min.js +27 -0
- package/examples/demo/streaming/media_devices_manager/manager.js +27 -1
- package/examples/demo/streaming/media_devices_manager/media_device_manager.html +7 -0
- package/examples/typescript/two-way-streaming-ts/.gitignore +23 -0
- package/examples/typescript/two-way-streaming-ts/README.md +36 -0
- package/examples/typescript/two-way-streaming-ts/package.json +45 -0
- package/examples/typescript/two-way-streaming-ts/public/favicon.ico +0 -0
- package/examples/typescript/two-way-streaming-ts/public/index.html +33 -0
- package/examples/typescript/two-way-streaming-ts/public/logo192.png +0 -0
- package/examples/typescript/two-way-streaming-ts/public/logo512.png +0 -0
- package/examples/typescript/two-way-streaming-ts/public/manifest.json +25 -0
- package/examples/typescript/two-way-streaming-ts/public/media/preloader.mp4 +0 -0
- package/examples/typescript/two-way-streaming-ts/public/robots.txt +3 -0
- package/examples/typescript/two-way-streaming-ts/src/TwoWayStreamingApp.css +23 -0
- package/examples/typescript/two-way-streaming-ts/src/TwoWayStreamingApp.tsx +371 -0
- package/examples/typescript/two-way-streaming-ts/src/fp-utils.ts +117 -0
- package/examples/typescript/two-way-streaming-ts/src/index.css +13 -0
- package/examples/typescript/two-way-streaming-ts/src/index.tsx +9 -0
- package/examples/typescript/two-way-streaming-ts/tsconfig.json +26 -0
- package/examples/vue/two-way-streaming-vue/.gitignore +23 -0
- package/examples/vue/two-way-streaming-vue/README.md +36 -0
- package/examples/vue/two-way-streaming-vue/babel.config.js +5 -0
- package/examples/vue/two-way-streaming-vue/package.json +47 -0
- package/examples/vue/two-way-streaming-vue/public/favicon.ico +0 -0
- package/examples/vue/two-way-streaming-vue/public/index.html +17 -0
- package/examples/vue/two-way-streaming-vue/src/TwoWayStreamingApp.vue +346 -0
- package/examples/vue/two-way-streaming-vue/src/assets/media/preloader.mp4 +0 -0
- package/examples/vue/two-way-streaming-vue/src/fp-utils.js +117 -0
- package/examples/vue/two-way-streaming-vue/src/main.js +9 -0
- package/examples/vue/two-way-streaming-vue/vue.config.js +8 -0
- package/flashphoner-no-flash.js +4 -4
- package/flashphoner-no-flash.min.js +1 -1
- package/flashphoner-no-webrtc.js +4 -4
- package/flashphoner-no-webrtc.min.js +1 -1
- package/flashphoner-no-wsplayer.js +4 -4
- package/flashphoner-no-wsplayer.min.js +1 -1
- package/flashphoner-room-api.js +4 -4
- package/flashphoner-room-api.min.js +1 -1
- package/flashphoner-temasys-flash-websocket-without-adapterjs.js +4 -4
- package/flashphoner-temasys-flash-websocket.js +4 -4
- package/flashphoner-temasys-flash-websocket.min.js +1 -1
- package/flashphoner-webrtc-only.js +4 -4
- package/flashphoner-webrtc-only.min.js +1 -1
- package/flashphoner.js +4 -4
- package/flashphoner.min.js +1 -1
- package/package.json +2 -1
- package/src/constants.d.ts +1 -0
- package/src/flashphoner-core.d.ts +192 -0
- package/src/flashphoner-core.js +4 -4
- package/src/room-module.d.ts +29 -0
- 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
|
+
}
|
|
Binary file
|
|
@@ -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>
|
|
Binary file
|
|
Binary file
|
|
@@ -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,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;
|