In this tutorial, we’ll look at how to retrieve a video stream from Motion with a React Native application.
Project configuration
We’ve set up a video stream with Motion on a Linux machine with address 192.168.1.92:8554 on the Wifi network.
The Motion program serves the video streams as an HTML page using the HTTP protocol. To retrieve this page, we use the react-native-webview library, which can display complete web pages in an application.
To install the library, enter the following command
npm install --save react-native-webview
Using WebView
To use the WebView component, simply import the
import {WebView} from 'react-native-webview'
and call the component in the App functional component renderer, specifying the video source
<View style={{flex: 1 }}>
<WebView
source={{uri: "http://192.168.1.92:8554/"}}
style={styles.webVideo} />
</View>
With the following style sheet
var styles = StyleSheet.create({
webVideo: {
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
},
});
To take this a step further, we’ve created a textInput insert that allows us to update the stream url (or web page) with ipAddress and ipServer states.
Details can be found in the full code.
The video is displayed with a delay of less than 3 seconds and a quality that is not very fluid.
Full code for the React Native application to play a Motion video stream
In the following code we define textInput, which will enable us to update the value of ipAddress (stored ip value) and, when the button is pressed, update the url read by the WebView component (ipServer)
We’ve also added a real-time date and time display (currentDate) to evaluate the delay in receiving the video stream. We’ve commented on this function because it refreshes the application every second.
/**
* https://github.com/react-native-webview/react-native-webview
*/
import React, { useEffect, useState } from 'react'
import { Text, View, StyleSheet, TextInput, TouchableOpacity } from 'react-native'
import {WebView} from 'react-native-webview'
const App = () => {
const videoRef = React.createRef();
const [ipAddress, setIpAddress] = useState("http://192.168.1.92:8554/");
const [ipServer, setIpServer] = useState("http://192.168.1.92:8554/");
//const [currentDate, setCurrentDate] = useState('');
useEffect(() => {
/*setInterval(() => {
var date = new Date().getDate(); //Current Date
var month = new Date().getMonth() + 1; //Current Month
var year = new Date().getFullYear(); //Current Year
var hours = new Date().getHours(); //Current Hours
var min = new Date().getMinutes(); //Current Minutes
var sec = new Date().getSeconds(); //Current Seconds
setCurrentDate(
date + '/' + month + '/' + year + ' ' + hours + ':' + min + ':' + sec
);
}, 1000)*/
}, []);
console.log("rendering...");
return (
<View style={{ flexGrow: 1, flex: 1 }}>
<Text style={styles.mainTitle}>AC Video Player</Text>
<View
style={styles.inputBar}>
<TextInput
style={styles.textInput}
placeholder="Enter a message"
value={ipAddress}
onChangeText={(text) => setIpAddress(text)
}
/>
<TouchableOpacity
onPress={() => {
setIpServer(""); //force state change thus rendering
setIpServer(ipAddress);}
}
style={[styles.sendButton]}>
<Text
style={styles.buttonText}>
SEND
</Text>
</TouchableOpacity>
</View>
<View style={{flex: 1 }}>
<WebView
source={{uri: ipServer}}
style={styles.webVideo} />
</View>
{/*<Text style={{textAlign: 'right'}}>{currentDate}</Text>*/}
</View>
)
}
export default App;
let BACKGROUND_COLOR = "#161616"; //191A19
let BUTTON_COLOR = "#346751"; //1E5128
let ERROR_COLOR = "#C84B31"; //4E9F3D
let TEXT_COLOR = "#ECDBBA"; //D8E9A8
var styles = StyleSheet.create({
mainTitle:{
color: TEXT_COLOR,
fontSize: 30,
textAlign: 'center',
borderBottomWidth: 2,
borderBottomColor: ERROR_COLOR,
},
webVideo: {
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
},
buttonText: {
color: TEXT_COLOR,
fontWeight: 'bold',
fontSize: 12,
textAlign: 'center',
textAlignVertical: 'center',
},
sendButton: {
backgroundColor: BUTTON_COLOR,
padding: 15,
borderRadius: 15,
margin: 2,
paddingHorizontal: 20,
},
inputBar:{
flexDirection: 'row',
justifyContent: 'space-between',
margin: 5,
},
textInput:{
backgroundColor: '#888888',
margin: 2,
borderRadius: 15,
flex:3,
},
});

