我有一些视频,希望在用户点击完整视频之前以缩略图的形式呈现。这些视频不是本地的,我只有URL。是否有RN组件可以实现这一点? RN Image组件无法将视频URL作为源。
我有一些视频,希望在用户点击完整视频之前以缩略图的形式呈现。这些视频不是本地的,我只有URL。是否有RN组件可以实现这一点? RN Image组件无法将视频URL作为源。
import React from 'react';
import { StyleSheet, Button, View, Image, Text } from 'react-native';
import * as VideoThumbnails from 'expo-video-thumbnails';
export default class App extends React.Component {
state = {
image: null,
};
generateThumbnail = async () => {
try {
const { uri } = await VideoThumbnails.getThumbnailAsync(
'http://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4',
{
time: 15000,
}
);
this.setState({ image: uri });
} catch (e) {
console.warn(e);
}
};
render() {
const { image } = this.state;
return (
<View style={styles.container}>
<Button onPress={this.generateThumbnail} title="Generate thumbnail" />
{image && <Image source={{ uri: image }} style={{ width: 200, height: 200 }} />}
<Text>{image}</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
});
-更新-
另一种方法是使用视频库而不播放视频和控制器。
例如:
npm install --save react-native-video
import Video from 'react-native-video';
// Within your render function, assuming you have a file called
// "background.mp4" in your project. You can include multiple videos
// on a single screen if you like.
<Video source={{uri: "background"}} // Can be a URL or a local file.
paused={true}
controls={false}
/>
很遗憾,目前没有react-native组件/api可以实现这一功能。但是,您可以利用本地操作系统api(在iOS上使用AVAssetImageGenerator
,在Android上使用MediaMetadataRetriever
)在您的react-native应用程序中从视频url生成缩略图。
对于快速解决方案,您可以使用react-native-create-thumbnail。它是上述系统api的封装,并支持远程和本地视频。
expo-video-thumbnails
轻松实现这一点。expo install expo-video-thumbnails
范例代码:
import React, { useState } from 'react';
import { StyleSheet, Button, View, Image, Text } from 'react-native';
import * as VideoThumbnails from 'expo-video-thumbnails';
export default function App() {
const [image, setImage] = useState(null);
const generateThumbnail = async () => {
try {
const { uri } = await VideoThumbnails.getThumbnailAsync(
'http://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4',
{
time: 15000,
}
);
setImage(uri);
} catch (e) {
console.warn(e);
}
};
return (
<View style={styles.container}>
<Button onPress={generateThumbnail} title="Generate thumbnail" />
{image && <Image source={{ uri: image }} style={styles.image} />}
<Text>{image}</Text>
</View>
);
}
Source: https://docs.expo.dev/versions/latest/sdk/video-thumbnails/#videothumbnailsoptions
"react-native-link-preview"
yarn add react-native-link-preview
LinkPreview.getPreview('https://www.youtube.com/watch?v=MejbOFk7H6c')
.then(data => console.debug(data));
完整代码:
import React, { Component } from 'react';
import { Text, View, FlatList, Image } from 'react-native';
import LinkPreview from 'react-native-link-preview';
let links = [
{
link: 'https://aws.amazon.com/'
},
{
link: 'https://firebase.google.com/'
},
{
link: 'https://www.youtube.com/watch?v=Kmiw4FYTg2U'
},
{
link: 'https://en.wikipedia.org/wiki/React_Native'
},
{
link:'https://stackoverflow.com/'
}
];
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
linkData: []
};
}
async componentDidMount() {
let _tempLinkData = [];
for (let link of links) {
await LinkPreview.getPreview(link.link)
.then(data => {
console.debug("Data : ", data);
let _newLinkDetails = {
link: link.link,
title: data.title,
thumbnail: data.images[0]
};
_tempLinkData.push(_newLinkDetails);
});
}
this.setState({ linkData: _tempLinkData });
}
render() {
return (
<View style={{ marginTop: 35 }}>
<FlatList
contentContainerStyle={{ paddingHorizontal: 20}}
data={this.state.linkData}
renderItem={({ item }) => (
<View style={{ flex: 1, flexDirection: "row", padding: 5 }}>
<Image
style={{ width: 50, height: 50 }}
source={{ uri: item.thumbnail }}
/>
<View style={{ marginLeft: 10, }}>
<Text style={{ fontSize: 16, lineHeight: 20, }}>{item.title}</Text>
<View style={{ flex: 1, flexDirection: "row", justifyContent: "space-between", }}>
<Text style={{ fontSize: 16, lineHeight: 20, color: "#a1a1a1" }}>{item.link}</Text>
</View>
</View>
</View>
)}
keyExtractor={(item, index) => String(index)}
/>
</View>
);
}
}
仅适用于Android:
事实证明你可以只使用<Image />
或<FastImage />
并传递视频源,只是不能选择用于缩略图的特定时间/帧。实际上要少麻烦得多。
来源:https://github.com/react-native-camera/react-native-camera/issues/700
使用Expo的VideoThumbnail
包真是一场噩梦,每次调用generateThumbnail()
时总是崩溃...
可以使用以下代码
<ImageBackground>
<View style={{alignItems:'center',marginTop:'50%'}}>
<Icon name='caret-forward-circle-outline' size={50} color={'#000'}/>
</View>
</ImageBackground>
-注意 我认为它在IOS上不起作用,但在安卓上是可能的。
import {createVideoThumbnail} from 'react-native-compressor'
const thumbnail = await createVideoThumbnail(videoFileUrl);