Nous allons voir dans ce tutoriel comment récupérer un flux vidéo Motion sur une application React Native.
Configuration du projet
Nous avons mis en place un stream vidéo avec Motion sur une machine Linux dont l’adresse est 192.168.1.92:8554 sur le réseau Wifi.
Le programme Motion sert les streams vidéo sous forme de page HTML avec le protocol HTTP. Pour récupérer cette page nous utilisons la librairie react-native-webview qui permet d’afficher des pages web complètes dans une application.
Pour installer la librairie, entrez la commande suivante
npm install --save react-native-webview
Utilisation de WebView
Pour utiliser le composant WebView, il nous suffit d’importer le composant
import {WebView} from 'react-native-webview'
et d’appeler le composant dans le rendu du composant fonctionnel App et de préciser la source de la vidéo
<View style={{flex: 1 }}> <WebView source={{uri: "http://192.168.1.92:8554/"}} style={styles.webVideo} /> </View>
Avec le style sheet suivant
var styles = StyleSheet.create({ webVideo: { position: 'absolute', top: 0, left: 0, bottom: 0, right: 0, }, });
Pour aller plus loin, nous avons créé une encart textInput qui nous permet de mettre à jour l’url du stream (ou de la page web) avec les états ipAddress et ipServer. Vous pouvez retrouver les détails dans le code complet.
La vidéo s’affiche avec un délai inférieur à 3secondes et une qualité qui n’est pas très fluide.
Code complet de l’application React Native pour lire un flux vidéo Motion
Dans le code suivant nous définissons textInput qui va nous permettre de mettre à jour la valeur de ipAddress (valeur d’ip stockée) et lorsqu’on appuit sur le bouton, mettre à jour l’url lu par le composant WebView (ipServer)
Nous avons aussi rajouter l’affichage de la date et de l’heure (currentDate) en temps réel pour évaluer le délai de réception du flux vidéo. Nous avons commenté cette fonction car elle rafraichit l’application toute les secondes.
/** * 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, }, });