Skip to content

Instantly share code, notes, and snippets.

@enricop89
Last active June 10, 2019 16:45
Show Gist options
  • Save enricop89/bb8fc27a22c47c9236434bdc11e49e56 to your computer and use it in GitHub Desktop.
Save enricop89/bb8fc27a22c47c9236434bdc11e49e56 to your computer and use it in GitHub Desktop.
RN Example App for OT Network Test
import React, { Component } from 'react';
import { Text, SafeAreaView, View } from 'react-native';
import { OTSession, OTPublisher, OTSubscriber, OT } from 'opentok-react-native';
import {VideoStats} from './networkTestHelper';
export default class App extends Component {
constructor( props ) {
super( props );
this.apiKey = '';
this.sessionId = '';
this.token = '';
this.sessionEventHandlers = {
sessionConnected: (event) => {
console.log( 'sessionConnected', event )
this.setState( { connection: 'Connected' } )
},
sessionDisconnected: () => {
console.log( 'sessionDisconnected' )
this.setState( { connection: 'Disconnected' } )
},
sessionDestroyed: () => {
console.log( 'sessionDestroyed' )
this.setState( { connection: 'Destroyed' } )
},
sessionReconnected: () => {
console.log( 'sessionReconnected' )
this.setState( { connection: 'Reconnected' } )
},
sessionReconnecting: () => {
console.log( 'sessionReconnecting' )
this.setState( { connection: 'Reconnecting' } )
},
error: error => {
// error: {message: "Invalid session id format", code: 1004}
console.log( 'Session error:', error );
this.setState( { error } )
},
otrnError: event => {
console.log( 'otRN error:', event );
},
streamCreated: stream => {
console.log('[sessionEventHandlers] - Stream created!', stream);
// this.handleStreamCreatedEvent(stream);
},
}
this.publisherEventHandlers = {
streamCreated: stream => {
console.log( '[publisherEventHandlers]', stream );
this.setState( { publisher: 'Publisher stream created' } )
this.handleStreamCreatedEvent(stream);
},
streamDestroyed: event => {
console.log( 'Publisher stream destroyed!', event );
this.setState( { publisher: 'Publisher stream destroyed' } )
},
otrnError: event => {
console.log( 'otRN Publisher error:', event );
}
};
this.subscriberEventHandlers = {
audioNetworkStats: (obj) => {
console.log( '[subscriberEventHandlers - audioNetworkStats]', obj );
},
videoNetworkStats: (obj) => {
console.log( '[subscriberEventHandlers - videoNetworkStats]', obj );
// this.VideoStatsHandler.checkVideoStats(obj.videoStats)
},
connected: () => {
console.log( '[subscriberEventHandlers - connected]' );
this.setState( { subscriber: 'Connected' } )
},
disconnected: () => {
console.log( '[subscriberEventHandlers - disconnected]' );
this.setState( { subscriber: 'Disconnected' } )
},
error: error => {
console.log( 'subscriberEventHandlers error:', error );
this.setState( { showSubscribeError: true, subscriberError: error } )
},
}
this.state = {
error: null,
connection: 'Connecting',
publisher: 'Stream not published',
subscriber: 'Stream not subscribed',
showPublishError: false,
publishError: null,
showSubscribeError: false,
subscriberError: null,
startTestTime: 0
}
this.VideoStatsHandler = null;
}
handleStreamCreatedEvent (stream) {
console.log( '[handleStreamCreatedEvent]', stream );
/* OT.subscribeToStream(stream.streamId, {subscribeToAudio: true,
subscribeToVideo: true}, (error) => {
if (error) {
console.log( '[handleStreamCreatedEvent]]', error );
} else {
console.log( '[handleStreamCreatedEvent]] - 2');
}
}); */
this.VideoStatsHandler = new VideoStats();
this._subscriberComponent.streamCreatedHandler(stream, {subscribeToAudio: true,
subscribeToVideo: true});
}
render () {
const { connection, error, publisher, publishError, showPublishError, showSubscribeError, subscriber, subscriberError } = this.state;
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
{<OTSession apiKey={this.apiKey} sessionId={this.sessionId} token={this.token} eventHandlers={this.sessionEventHandlers}>
<OTPublisher style={{ width: '100%', height: 300 }} eventHandlers={this.publisherEventHandlers}/>
<OTSubscriber ref={component => this._subscriberComponent = component} eventHandlers={this.subscriberEventHandlers}/>
</OTSession>}
</View>
<View style={{ alignItems: 'center', fontSize: 30}}>
<Text>OpenTok Network Test</Text>
</View>
<View style={{ flex: 1, flexDirection: 'column' }}>
<Text>Connection state: {connection}</Text>
<Text>Error: {JSON.stringify( error )}</Text>
{showPublishError ? <Text>Publisher: {JSON.stringify( publishError )}</Text> : <Text>Publisher: {publisher}</Text>}
{showSubscribeError ? <Text>Subscriber: {JSON.stringify( subscriberError )}</Text> : <Text>Subscriber: {subscriber}</Text>}
</View>
</View>
</SafeAreaView>
);
}
}
const TIME_WINDOW = 3; //3 seconds
class VideoStats {
constructor() {
this.prevVideoTimestamp = 0;
this.prevVideoPacketsLost = 0;
this.prevVideoPacketsRcvd = 0;
this.prevVideoBytes = 0;
this.videoPLRatio = 0;
this.videoBw = 0;
}
checkVideoStats(stats) {
console.log('[checkVideoStats] - ', stats)
let videoTimestamp = new Date().getTime() / 1000;
if (this.prevVideoTimestamp === 0) {
this.prevVideoTimestamp = videoTimestamp;
this.prevVideoBytes = stats.videoBytesReceived;
}
if (videoTimestamp - this.prevVideoTimestamp >= TIME_WINDOW) {
//calculate video packets lost ratio
if (this.prevVideoPacketsRcvd != 0) {
const pl = stats.videoPacketsLost - this.prevVideoPacketsLost;
let pr = stats.videoPacketsReceived - this.prevVideoPacketsRcvd;
let pt = pl + pr;
if (pt > 0) {
this.videoPLRatio = pl / pt;
}
}
this.prevVideoPacketsLost = stats.videoPacketsLost;
this.prevVideoPacketsRcvd = stats.videoPacketsReceived;
//calculate video bandwidth
this.videoBw = ((8 * (stats.videoBytesReceived - this.prevVideoBytes)) / (videoTimestamp - this.prevVideoTimestamp));
this.prevVideoTimestamp = videoTimestamp;
this.prevVideoBytes = stats.videoBytesReceived;
console.log('Video bandwidth', this.videoBw);
console.log('Video Bytes received', stats.videoBytesReceived);
console.log('Video packet lost:', stats.videoPacketsLost);
console.log('Video packet loss ratio:', this.videoPLRatio);
}
}
}
export {
VideoStats
}
@enricop89
Copy link
Author

enricop89 commented Jun 10, 2019

This App should:

  1. connect to an OT Session
  2. publish a stream
  3. in the streamCreated Event of the Publisher, subscribe to my own stream.
  4. I use ref in the OTSubscriber component to subscribe the App to my own stream

What I obtain:

  • iOS: everything is fine, the App subscribes to his own stream and receive audio/video stats
  • Android: see image attached

Screenshot 2019-06-10 at 5 05 22 pm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment