Reputation: 2665
I have a requirement to play Vimeo videos in my react native app. I am using webview to play videos, Videos play but I can not see anything on screen, audio is coming but the screen is blank. Below is my code. Is there something I am doing wrong or any other way to play Vimeo ? Any help would be appreciated.
<AutoHeightWebView
startInLoadingState
style={{ width: "100%", height: '100%', borderColor: 'white', borderWidth: 2 }}
source={{
uri: 'https://player.vimeo.com/video/299264098?autoplay=1' //'this.state.videoUrl'
}}
onError={() => console.log('on error')}
onLoad={() => console.log('on load')}
onLoadStart={() => console.log('on load start')}
onLoadEnd={() => console.log('on load end')}
bounces={false}
/>
Upvotes: 6
Views: 27078
Reputation: 1266
Bit late to answer but anyone seeking the solution yet, can either use React Native Video or Can use Iframe from package react-native-vimeo-iframe
Will share the code to use with react-native-vimeo-iframe
import React, { useState } from 'react';
import { View, StyleSheet, Text } from 'react-native';
import { Vimeo } from 'react-native-vimeo-iframe';
const VideoPlayer = ({ videoId }) => {
// ...
}
const [isPlaying, setIsPlaying] = useState(false);
const [currentTime, setCurrentTime] = useState(0);
const [played, setPlayed] = useState(0);
const [loaded, setLoaded] = useState(0);
const [volume, setVolume] = useState(1);
const [error, setError] = useState(null);
const handleReady = () => {
console.log('Player is ready');
};
const handlePlay = () => {
console.log('Video started playing');
setIsPlaying(true);
};
const handlePause = () => {
console.log('Video paused');
setIsPlaying(false);
};
const handleEnded = () => {
console.log('Video ended');
setIsPlaying(false);
};
const handleTimeUpdate = ({ currentTime, duration }) => {
console.log('Current time:', currentTime);
setCurrentTime(currentTime);
};
const handleProgress = ({ played, loaded }) => {
console.log('Played:', played, 'Loaded:', loaded);
setPlayed(played);
setLoaded(loaded);
};
const handleSeeked = () => {
console.log('Seeked to new position');
};
const handleVolumeChange = (newVolume) => {
console.log('Volume changed to:', newVolume);
setVolume(newVolume);
};
const handleError = (error) => {
console.log('Error:', error);
setError(error);
};
return (
<View style={styles.container}>
<Vimeo
videoId={videoId}
autoplay={false}
loop={false}
controls={true}
onReady={handleReady}
onPlay={handlePlay}
onPause={handlePause}
onEnded={handleEnded}
onTimeUpdate={handleTimeUpdate}
onProgress={handleProgress}
onSeeked={handleSeeked}
onVolumeChange={handleVolumeChange}
onError={handleError}
/>
<Text style={styles.text}>
{isPlaying ? 'Playing' : 'Paused'} at {currentTime} seconds
</Text>
<Text style={styles.text}>
Played: {played.toFixed(2)}, Loaded: {loaded.toFixed(2)}
</Text>
<Text style={styles.text}>Volume: {volume.toFixed(2)}</Text>
{error && <Text style={styles.text}>Error: {error.message}</Text>}
</View>
);
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#000',
},
text: {
color: '#fff',
textAlign: 'center',
marginVertical: 10,
},
});
export default VideoPlayer;
Upvotes: 2
Reputation: 8982
You can use the oEmbed api that Vimeo provides. It will generate an embeddable <iframe>
element for the video in question. You can use a function in a hook like this:
React.useEffect(() => {
setLoading(true);
(async function init() {
try {
const urlParts = url.split("/");
const channelID = urlParts[urlParts.length - 2];
const videoID = urlParts[urlParts.length - 1];
const videoURL = `https://vimeo.com/${channelID}/${videoID}`;
const requestURL = `https://vimeo.com/api/oembed.json?url=${videoURL}&height=${400}`;
const { data } = await axios(requestURL);
setHtml(data.html);
} catch (err) {
console.error(err);
} finally {
setLoading(false);
}
})();
}, [url]);
The videoURL
parameter will depend on the kind of channel the video was posted on.
Upvotes: 0
Reputation: 642
Short answer: Use the progressive
files, not hls
.
These seem to contain links to mp4-files, which expo-av
supports on both Android and iOS, no matter if your project is a bare React Native project, or managed by Expo.
Similar to the solution posted by Zuhair Naqi, but use the url from an object in res.request.files.progressive
, rather than res.request.files.hls.cdns[res.request.files.hls.default_cdn].url
The function in the below example will return a list of objects containing links to that video at different resolutions.
function getVimeoLinks(url: string) {
return fetch(`https://vimeo.com/api/oembed.json?url=${url}`, {
headers: {
'content-type': 'application/json',
accept: 'application/json'
}
})
.then(r => r.json())
.then(({ video_id }) =>
fetch(`https://player.vimeo.com/video/${video_id}/config`)
)
.then(r => r.json())
.then(
r =>
r.request.files.progressive as {
profile: number;
width: number;
mime: string;
fps: number;
url: string;
cdn: string;
quality: string;
id: number;
origin: string;
height: number;
}[]
);
}
then, for your component, do something like this:
import { Video } from 'expo-av';
// Hook for getting some Vimeo video url (mp4)
function useVimeoUrl(url: string) {
const [state, setState] = useState<undefined | string>();
useEffect(() => {
getVimeoConfig(url).then(r => setState(r[0].url));
}, [url]);
return state;
}
// Render video
function MyComponent({ url }: { url: string }) {
// State containing video url
const vimeoUrl = useVimeoUrl(url);
// Render
return vimeoUrl ? <Video source={{ uri: vimeoUrl }} /> : <></>;
}
Upvotes: 3
Reputation: 61
I was facing the same problem trying to display an embed Vimeo video in my app. The solution, using html
content, as shown from Juliano worked very well for me
Upvotes: 1
Reputation: 221
I found a solution with embed iframe on webview.
import React from 'react';
import { string, func } from 'prop-types';
import WebView from 'react-native-autoheight-webview';
const VimeoPlayer = ({ videoId, onError }) => {
return (
<WebView
style={style}
onError={onError}
allowsFullscreenVideo
scrollEnabled={false}
automaticallyAdjustContentInsets
source={{
html: `
<html>
<body>
<iframe src="https://player.vimeo.com/video/${videoId}" width="100%" height="200px" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
<script src="https://player.vimeo.com/api/player.js"></script>
</body>
</html>
`,
}}
/>
);
};
const style = {
height: 200,
maxWidth: '100%',
};
VimeoPlayer.propTypes = {
videoId: string,
onError: func,
};
export default VimeoPlayer;
Upvotes: 6
Reputation: 1270
I found a way to run a vimeo video in react native. simply you've to request on URL to get it's detail config through vimeo id. Inside config you'll find videoUrl, that can be easily run on react-native-video-controls.
Here is example
const VIMEO_ID = '179859217';
fetch(`https://player.vimeo.com/video/${VIMEO_ID}/config`)
.then(res => res.json())
.then(res => this.setState({
thumbnailUrl: res.video.thumbs['640'],
videoUrl: res.request.files.hls.cdns[res.request.files.hls.default_cdn].url,
video: res.video,
}));
In Render
<VideoPlayer
ref={ref => {
this.player = ref;
}}
source={{uri: this.state.videoUrl}}
navigator={this.props.navigator}
fullscreen={true}
resizeMode={'cover'}
/>
Upvotes: 18
Reputation: 4409
Try react-native-video
package to play Vimeo
videos in React Native project.
To install with npm
npm install --save react-native-video
or using yarn
:
yarn add react-native-video
It is worth noting the issues that may occur in the links below.
https://stackoverflow.com/a/52976151/5519329
https://stackoverflow.com/a/39982973/5519329
Code:
import Video from 'react-native-video';
<Video source={{uri: "your url"}} // Can be a URL or a local file.
ref={(ref) => {
this.player = ref
}} // Store reference
onBuffer={this.onBuffer} // Callback when remote video is buffering
onEnd={this.onEnd} // Callback when playback finishes
onError={this.videoError} // Callback when video cannot be loaded
style={styles.backgroundVideo} />
// Later on in your styles..
var styles = StyleSheet.create({
backgroundVideo: {
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
},
});
Upvotes: 2