openvidu-react-native: Added mute/unmute camera funcionality

This commit is contained in:
CSantos 2019-07-09 16:32:27 +02:00
parent 915350e8e3
commit e4f284f60a
2 changed files with 128 additions and 78 deletions

View File

@ -7,7 +7,19 @@
*/ */
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Platform,TextInput, ScrollView, Button, Alert, Linking, StyleSheet, Text, View, PermissionsAndroid } from 'react-native'; import {
Platform,
TextInput,
ScrollView,
Button,
Alert,
Linking,
StyleSheet,
Text,
View,
Image,
PermissionsAndroid,
} from 'react-native';
import { OpenVidu } from 'openvidu-browser'; import { OpenVidu } from 'openvidu-browser';
import { RTCView } from './node_modules/openvidu-browser/node_modules/react-native-webrtc'; import { RTCView } from './node_modules/openvidu-browser/node_modules/react-native-webrtc';
@ -16,6 +28,7 @@ import axios from 'axios';
const OPENVIDU_SERVER_URL = 'https://demos.openvidu.io:4443'; const OPENVIDU_SERVER_URL = 'https://demos.openvidu.io:4443';
const OPENVIDU_SERVER_SECRET = 'MY_SECRET'; const OPENVIDU_SERVER_SECRET = 'MY_SECRET';
type Props = {}; type Props = {};
export default class App extends Component<Props> { export default class App extends Component<Props> {
constructor(props) { constructor(props) {
@ -30,11 +43,11 @@ export default class App extends Component<Props> {
role: 'PUBLISHER', role: 'PUBLISHER',
mirror: true, mirror: true,
videoSource: undefined, videoSource: undefined,
camera: true,
}; };
} }
componentDidMount() { componentDidMount() {}
}
componentWillUnmount() { componentWillUnmount() {
this.leaveSession(); this.leaveSession();
@ -130,14 +143,12 @@ export default class App extends Component<Props> {
mySession mySession
.connect(token, { clientData: this.state.myUserName }) .connect(token, { clientData: this.state.myUserName })
.then(() => { .then(() => {
if (Platform.OS == 'android') { if (Platform.OS == 'android') {
this.checkAndroidPermissions(); this.checkAndroidPermissions();
} }
// --- 5) Get your own camera stream --- // --- 5) Get your own camera stream ---
if (this.state.role !== 'SUBSCRIBER') { if (this.state.role !== 'SUBSCRIBER') {
const properties = { const properties = {
audioSource: undefined, // The source of audio. If undefined default microphone audioSource: undefined, // The source of audio. If undefined default microphone
videoSource: undefined, // The source of video. If undefined default webcam videoSource: undefined, // The source of video. If undefined default webcam
@ -146,7 +157,7 @@ export default class App extends Component<Props> {
resolution: '640x480', // The resolution of your video resolution: '640x480', // The resolution of your video
frameRate: 30, // The frame rate of your video frameRate: 30, // The frame rate of your video
insertMode: 'APPEND', // How the video is inserted in the target element 'video-container' insertMode: 'APPEND', // How the video is inserted in the target element 'video-container'
} };
// Init a publisher passing undefined as targetElement (we don't want OpenVidu to insert a video // Init a publisher passing undefined as targetElement (we don't want OpenVidu to insert a video
// element: we will manage it on our own) and with the desired properties // element: we will manage it on our own) and with the desired properties
let publisher = this.OV.initPublisher(undefined, properties); let publisher = this.OV.initPublisher(undefined, properties);
@ -156,11 +167,10 @@ export default class App extends Component<Props> {
// Set the main video in the page to display our webcam and store our Publisher // Set the main video in the page to display our webcam and store our Publisher
this.setState({ this.setState({
mainStreamManager: publisher, mainStreamManager: publisher,
videoSource: !properties.videoSource ? '1' : properties.videoSource // 0: back camera | 1: user camera | videoSource: !properties.videoSource ? '1' : properties.videoSource, // 0: back camera | 1: user camera |
}); });
mySession.publish(publisher); mySession.publish(publisher);
} }
}) })
.catch((error) => { .catch((error) => {
console.log('There was an error connecting to the session:', error.code, error.message); console.log('There was an error connecting to the session:', error.code, error.message);
@ -173,7 +183,7 @@ export default class App extends Component<Props> {
getNicknameTag(stream) { getNicknameTag(stream) {
// Gets the nickName of the user // Gets the nickName of the user
if(stream.connection && JSON.parse(stream.connection.data) && JSON.parse(stream.connection.data).clientData) { if (stream.connection && JSON.parse(stream.connection.data) && JSON.parse(stream.connection.data).clientData) {
return JSON.parse(stream.connection.data).clientData; return JSON.parse(stream.connection.data).clientData;
} }
return ''; return '';
@ -212,18 +222,20 @@ export default class App extends Component<Props> {
mainStreamManager: undefined, mainStreamManager: undefined,
publisher: undefined, publisher: undefined,
}); });
}) });
} }
toggleCamera(){ toggleCamera() {
/** /**
* _switchCamera() Method provided by react-native-webrtc: * _switchCamera() Method provided by react-native-webrtc:
* This function allows to switch the front / back cameras in a video track on the fly, without the need for adding / removing tracks or renegotiating * This function allows to switch the front / back cameras in a video track on the fly, without the need for adding / removing tracks or renegotiating
*/ */
this.state.mainStreamManager.stream.getMediaStream().getVideoTracks()[0]._switchCamera(); this.state.mainStreamManager.stream
this.setState({mirror: !this.state.mirror}); .getMediaStream()
.getVideoTracks()[0]
._switchCamera();
this.setState({ mirror: !this.state.mirror });
/** /**
* Traditional way: * Traditional way:
@ -257,76 +269,105 @@ export default class App extends Component<Props> {
*/ */
} }
render() { muteUnmuteCamera() {
this.state.mainStreamManager.publishVideo(!this.state.camera);
this.setState({ camera: !this.state.camera });
}
render() {
return ( return (
<ScrollView> <ScrollView>
{this.state.mainStreamManager ? ( {this.state.mainStreamManager ? (
<View> <View>
<View style={styles.container}> <View style={styles.container}>
<Text>Session: {this.state.mySessionId}</Text> <Text>Session: {this.state.mySessionId}</Text>
<Text>{this.getNicknameTag(this.state.mainStreamManager.stream)}</Text> <Text>{this.getNicknameTag(this.state.mainStreamManager.stream)}</Text>
<RTCView zOrder={0} objectFit="cover" mirror={this.state.mirror} <RTCView
ref={(rtcVideo) => { zOrder={0}
if (!!rtcVideo) { objectFit="cover"
this.state.mainStreamManager.addVideoElement(rtcVideo); mirror={this.state.mirror}
} ref={(rtcVideo) => {
}} if (!!rtcVideo) {
style={styles.selfView} this.state.mainStreamManager.addVideoElement(rtcVideo);
/> }
</View> }}
<View> style={styles.selfView}
<Button
onLongPress={() => this.toggleCamera()}
onPress={() => this.toggleCamera()}
title="Toggle Camera"
color="#841584"
/> />
<Button </View>
onLongPress={() => this.leaveSession()} <View>
onPress={() => this.leaveSession()} <View style={styles.button}>
title="Leave Session" <Button
color="#ff0000" onLongPress={() => this.toggleCamera()}
/> onPress={() => this.toggleCamera()}
</View> title="Toggle Camera"
color="#841584"
/>
</View>
<View style={styles.button}>
<Button
onLongPress={() => this.muteUnmuteCamera()}
onPress={() => this.muteUnmuteCamera()}
title={this.state.camera ? 'Mute Camera' : 'Unmute Camera'}
color="#00cbff"
/>
</View>
<View style={styles.button}>
<Button
onLongPress={() => this.leaveSession()}
onPress={() => this.leaveSession()}
title="Leave Session"
color="#ff0000"
/>
</View>
</View>
</View> </View>
) : ( ) : (
<View style={{ <View>
flex: 1, <View style={{
flexDirection: 'column', justifyContent: 'center',
justifyContent: 'center', alignItems: 'center',
alignItems: 'stretch', padding: 20}}>
height: '100%',
paddingTop: 100 <Image style={styles.img} source={require('./resources/images/openvidu_grey_bg_transp_cropped.png')} />
}}> </View>
<TextInput <View style={{ justifyContent: 'center', alignItems: 'center'}}>
style={{height: 40, borderColor: 'gray', borderWidth: 1}} <TextInput
onChangeText={(mySessionId) => this.setState({mySessionId})} style={{ width: '90%', height: 40, borderColor: 'gray', borderWidth: 1 }}
value={this.state.mySessionId} onChangeText={(mySessionId) => this.setState({ mySessionId })}
/> value={this.state.mySessionId}
<Button
onLongPress={() => this.joinSession()}
onPress={() => this.joinSession()}
title="Join"
color="#841584"
style={{width: '100%'}}
/> />
</View>
<View style={styles.button}>
<Button
onLongPress={() => this.joinSession()}
onPress={() => this.joinSession()}
title="Join"
color="#841584"
/>
</View>
</View> </View>
)} )}
<View style={[styles.container, {flexDirection: 'row', flexWrap: 'wrap'}] }> <View style={[styles.container, { flexDirection: 'row', flexWrap: 'wrap' }]}>
{this.state.subscribers.map((item, index) => { {this.state.subscribers.map((item, index) => {
if(!!item){ if (!!item) {
return ( return (
<View key={index}> <View key={index}>
<Text>{this.getNicknameTag(item.stream)}</Text> <Text>{this.getNicknameTag(item.stream)}</Text>
<RTCView zOrder={0} objectFit="cover" style={styles.remoteView} ref={(rtcVideo) => { <RTCView
if (!!rtcVideo){ zOrder={0}
item.addVideoElement(rtcVideo); objectFit="cover"
} style={styles.remoteView}
}} /> ref={(rtcVideo) => {
if (!!rtcVideo) {
item.addVideoElement(rtcVideo);
}
}}
/>
</View> </View>
) );
} }
})} })}
</View> </View>
@ -354,14 +395,13 @@ export default class App extends Component<Props> {
createSession(sessionId) { createSession(sessionId) {
return new Promise((resolve) => { return new Promise((resolve) => {
var data = JSON.stringify({ customSessionId: sessionId }); var data = JSON.stringify({ customSessionId: sessionId });
axios axios
.post(OPENVIDU_SERVER_URL + '/api/sessions', data, { .post(OPENVIDU_SERVER_URL + '/api/sessions', data, {
headers: { headers: {
Authorization: 'Basic ' + btoa('OPENVIDUAPP:' + OPENVIDU_SERVER_SECRET), Authorization: 'Basic ' + btoa('OPENVIDUAPP:' + OPENVIDU_SERVER_SECRET),
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Accept': 'application/json' Accept: 'application/json',
}, },
}) })
.then((response) => { .then((response) => {
@ -375,7 +415,9 @@ export default class App extends Component<Props> {
console.log('RESOLVING WITH SESSIONID, 409'); console.log('RESOLVING WITH SESSIONID, 409');
resolve(sessionId); resolve(sessionId);
} else { } else {
console.warn('No connection to OpenVidu Server. This may be a certificate error at ' + OPENVIDU_SERVER_URL); console.warn(
'No connection to OpenVidu Server. This may be a certificate error at ' + OPENVIDU_SERVER_URL,
);
Alert.alert( Alert.alert(
'No connection to OpenVidu Server.', 'No connection to OpenVidu Server.',
@ -430,14 +472,22 @@ const styles = StyleSheet.create({
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
flex: 1, flex: 1,
paddingTop: Platform.OS == 'ios' ? 20 : 0 paddingTop: Platform.OS == 'ios' ? 20 : 0,
}, },
selfView: { selfView: {
width: 200, width: '100%',
height: 200, height: 300,
}, },
remoteView: { remoteView: {
width: 150, width: 150,
height: 150, height: 150,
}, },
button: {
padding: 10,
},
img: {
flex: 1,
width: 400,
height: 200,
}
}); });

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB