fbpixel
Étiquettes : ,

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import {WebView} from 'react-native-webview'
import {WebView} from 'react-native-webview'
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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<View style={{flex: 1 }}>
<WebView
source={{uri: "http://192.168.1.92:8554/"}}
style={styles.webVideo} />
</View>
<View style={{flex: 1 }}> <WebView source={{uri: "http://192.168.1.92:8554/"}} style={styles.webVideo} /> </View>
      <View style={{flex: 1 }}>

            <WebView
              source={{uri: "http://192.168.1.92:8554/"}}
              style={styles.webVideo} />

      </View>

Avec le style sheet suivant

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
var styles = StyleSheet.create({
webVideo: {
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
},
});
var styles = StyleSheet.create({ webVideo: { position: 'absolute', top: 0, left: 0, bottom: 0, right: 0, }, });
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.

react-native-webview-motion-video-stream Afficher un Stream Vidéo Motion sur React Native

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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/**
* 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,
},
});
/** * 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, }, });
/**
 * 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,
  },
});

Sources