En este tutorial veremos cómo recuperar un flujo de vídeo Motion desde una aplicación React Native.
Configuración del proyecto
Hemos configurado un flujo de vídeo con Motion en una máquina Linux cuya dirección es 192.168.1.92:8554 en la red Wifi.
El programa Motion sirve las secuencias de vídeo en forma de página HTML mediante el protocolo HTTP. Para recuperar esta página utilizamos la biblioteca react-native-webview, que puede mostrar páginas web completas en una aplicación.
Para instalar la biblioteca, introduzca el siguiente comando
npm install --save react-native-webview
Uso de WebView
Para utilizar el componente WebView, todo lo que tenemos que hacer es importar el archivo
import {WebView} from 'react-native-webview'
y llame al componente en el renderizado del componente funcional App y especifique la fuente del vídeo
<View style={{flex: 1 }}> <WebView source={{uri: "http://192.168.1.92:8554/"}} style={styles.webVideo} /> </View>
Con el siguiente estilo de hoja
var styles = StyleSheet.create({ webVideo: { position: 'absolute', top: 0, left: 0, bottom: 0, right: 0, }, });
Para ir un paso más allá, hemos creado una inserción textInput que nos permite actualizar la url del stream (o página web) con los estados ipAddress e ipServer. Puedes encontrar los detalles en el código completo.
El vídeo se muestra con un retardo de menos de 3 segundos y una calidad poco fluida.
Código completo de la aplicación React Native para reproducir un flujo de vídeo Motion.
En el siguiente código definimos textInput que nos permitirá actualizar el valor de ipAddress (valor de ip almacenado) y al pulsar el botón, actualizar la url leída por el componente WebView (ipServer)
También hemos añadido la visualización de la fecha y la hora (currentDate) en tiempo real para evaluar el retraso en la recepción del flujo de vídeo. Comentamos esta función porque refresca la aplicación cada segundo.
/** * 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, }, });