【问题标题】:React Native generate thumbnail for video urlReact Native 为视频 url 生成缩略图
【发布时间】:2022-04-14 01:16:39
【问题描述】:

我希望在用户点击视频以查看完整视频之前将其显示为缩略图。他们不是本地的,我只有网址。是否有 RN 组件可以做到这一点? RN Image 组件不将视频 url 作为来源。

【问题讨论】:

  • 你有没有想过这个问题?我无法找到获取实际视频文件的方法。
  • 我还没有遇到任何事情@Keng​​span>

标签: javascript reactjs video react-native


【解决方案1】:

不可能。视频缩略图不能从视频 URL 自动生成。它应该与后端数据库中的视频一起创建和存储,当 RN 应用程序接收到视频 URL 时,它也应该接收到缩略图 URL。然后可以使用ImageTouchableOpacity 组件在缩略图上添加按压行为。

但是,如果您只使用 Youtube 视频,那么 react-native-thumbnail-video 可能是您问题的快速解决方案。

【讨论】:

    【解决方案2】:

    不幸的是,没有 react-native 组件/api 可以做到这一点。但是,您可以利用本机操作系统 API(iOS 上的 AVAssetImageGenerator 和 android 上的 MediaMetadataRetriever)从您的 react-native 应用程序中的视频 url 生成缩略图。

    如需快速解决方案,您可以使用react-native-create-thumbnail。它是上述系统 API 的封装,支持远程和本地视频。

    【讨论】:

      【解决方案3】:

      可以使用Expo Video Thumbnail library

      就像这个例子

      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}
      />
      

      在这个例子中,它会显示视频而不播放它,所以基本上会给你缩略图。

      P.S:如果您在同一视图中有多个视频超过 10 个,则不推荐。

      【讨论】:

      • 但它不适用于本地视频文件。你有什么主意吗? @Balalen
      • 另一种方法是,加载视频播放器而不播放它,这样它会显示缩略图而不播放视频,我编辑了答案,看看
      • 前几天我忘记在这里回复了。实际上 expo-video-thumbnails 也适用于本地视频文件。我在本地遇到了一些编码问题,那就是它不起作用。但是当我交叉检查时,它工作正常。感谢@Balalen 的回复
      • @Balalen expo-video-thumbnails 对我来说很好用,谢谢!
      • 我在 IOS 中遇到错误 [错误:无法写入文件。]
      【解决方案4】:

      您可以通过以下步骤做到这一点:

      第 1 步:使用以下命令在当前项目上安装 "react-native-link-preview" 包:

      yarn add react-native-link-preview
      

      第 2 步:这是您可以获取链接详细信息的代码:如链接标题、链接缩略图等。

      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>
      
              );
          }
      }
      

      【讨论】:

        【解决方案5】:

        仅适用于 Android:

        原来您可以只使用&lt;Image /&gt;&lt;FastImage /&gt; 并传递视频源,您只是无法选择用于缩略图的特定时间/帧。少了很多麻烦。

        来源:https://github.com/react-native-camera/react-native-camera/issues/700

        使用 Expo 的 VideoThumbnail 包是一场噩梦,当尝试在 null 上调用 generateThumbnail() 时总是导致应用程序崩溃...

        【讨论】:

          【解决方案6】:

          我使用这个包 React Native Create Thumbnail 从视频 URL 创建缩略图。阅读文档,它非常易于使用。

          【讨论】:

            猜你喜欢
            • 2017-03-01
            • 2011-02-19
            • 2017-10-14
            • 2012-09-01
            • 2011-07-04
            • 1970-01-01
            • 2013-10-22
            • 2016-09-17
            • 2012-02-12
            相关资源
            最近更新 更多