react-native-video使用攻略


源碼在此 僅供參考


一、簡(jiǎn)介

react-native-video是一個(gè)可以播放視頻的組件,它的用法簡(jiǎn)單,功能完備,是React native項(xiàng)目中很好用的一個(gè)Video播放的組件。

它的功能主要有以下10個(gè):

  1. 控制播放速率
  2. 控制音量大小
  3. 支持靜音功能
  4. 支持播放和暫停
  5. 支持后臺(tái)音頻播放
  6. 支持定制樣式,比如設(shè)置寬高
  7. 豐富的事件調(diào)用,如onLoad,onEnd,onProgress,onBuffer等等,可以通過對(duì)應(yīng)的事件進(jìn)行UI上的定制處理,如onBuffer時(shí)我們可以顯示一個(gè)進(jìn)度條提示用戶視頻正在緩沖。
  8. 支持全屏播放,使用presentFullscreenPlayer方法。這個(gè)方法在iOS上可行,在android上不起作用。參看issue#534,#726也是同樣的問題。
  9. 支持跳轉(zhuǎn)進(jìn)度,使用seek方法跳轉(zhuǎn)到指定的地方進(jìn)行播放
  10. 可以加載遠(yuǎn)程視頻地址進(jìn)行播放,也可以加載RN本地存放的視頻。

二、使用

使用步驟如下:

  1. 導(dǎo)入依賴庫

在項(xiàng)目Terminal中輸入命令行:

npm install react-native-video --save

或者用yarn:

yarn add react-native-video

IOS環(huán)境下:

直接運(yùn)行下面命令來鏈接react-native-video庫。

react-native link 

如果你想允許其他應(yīng)用在你的視頻組件上播放音樂,請(qǐng)打開AppDelegate.m文件并且添加:

AppDelegate.m

#import <AVFoundation/AVFoundation.h>  // import

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  ...
  [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];  // allow
  ...
}

Android環(huán)境下:

直接運(yùn)行下面命令來鏈接react-native-video庫。

react-native link 

如果上面的方式失敗了,那么你可以嘗試手動(dòng)添加配置,這步比較麻煩。

android/settings.gradle
較新的ExoPlayer庫適用于大多數(shù)人。(推薦使用這個(gè)庫)

include ':react-native-video'
project(':react-native-video').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android-exoplayer')

如果您需要使用舊的基于Android MediaPlayer的播放器,請(qǐng)改用以下內(nèi)容:

include ':react-native-video'
project(':react-native-video').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android')

android/app/build.gradle

dependencies {
   ...
   compile project(':react-native-video')
}

MainApplication.java
在java文件頂部位置記得添加import:

import com.brentvatne.react.ReactVideoPackage;

將ReactVideoPackage類添加到導(dǎo)出的包列表中:

@Override
protected List<ReactPackage> getPackages() {
    return Arrays.asList(
            new MainReactPackage(),
            new ReactVideoPackage()
    );
}

三、案例分析

screen

上面這張動(dòng)圖可以看出,我們可以通過自定義的樣式和功能來使用react-native-video。
其中實(shí)現(xiàn)的功能有:調(diào)節(jié)播放速率,調(diào)節(jié)視頻音量,以及調(diào)節(jié)視頻播放器的樣式,這三個(gè)功能分別對(duì)應(yīng)下圖中的三個(gè)紅色邊框離的選項(xiàng)。


screenshot

此外,我們還給這個(gè)視頻播放器組件添加了很多事件屬性,例如播放進(jìn)度條的監(jiān)聽(onProgress),播放完回到視頻起點(diǎn)的設(shè)置(onEnd)等,下面我們跟隨代碼一步步分析這個(gè)組件的一些屬性和用法。

  • 首先我們聲明一個(gè)組件來使用這個(gè)Video,在此之前先將它導(dǎo)進(jìn)來
import React, {
    Component
} from 'react';

import {
    StyleSheet,
    Text,
    TouchableOpacity,
    View,
} from 'react-native';

import Video from 'react-native-video';

export default class VideoPlayer extends Component {
      ···  ···
}
  • 接著初始化一些state,之后會(huì)用到。比如rate表示視頻播放速率初始化為1,即正常速率。
 state = {
        rate: 1,
        volume: 1,
        muted: false,
        resizeMode: 'contain',
        duration: 0.0,
        currentTime: 0.0,
        paused: true,
    };
  • 渲染Video組件
<Video
    ref={(ref: Video) => { //方法對(duì)引用Video元素的ref引用進(jìn)行操作
        this.video = ref
    }}
    /* source={{ uri: 'https://gslb.miaopai.com/stream/HNkFfNMuhjRzDd-q6j9qycf54OaKqInVMu0YhQ__.mp4?ssig=bbabfd7684cae53660dc2d4c2103984e&time_stamp=1533631567740&cookie_id=&vend=1&os=3&partner=1&platform=2&cookie_id=&refer=miaopai&scid=HNkFfNMuhjRzDd-q6j9qycf54OaKqInVMu0YhQ__', type: 'mpd' }} */
    source={require('../../background.mp4')}//設(shè)置視頻源  
    style={styles.fullScreen}//組件樣式
    rate={this.state.rate}//播放速率
    paused={this.state.paused}//暫停
    volume={this.state.volume}//調(diào)節(jié)音量
    muted={this.state.muted}//控制音頻是否靜音
    resizeMode={this.state.resizeMode}//縮放模式
    onLoad={this.onLoad}//加載媒體并準(zhǔn)備播放時(shí)調(diào)用的回調(diào)函數(shù)。
    onProgress={this.onProgress}//視頻播放過程中每個(gè)間隔進(jìn)度單位調(diào)用的回調(diào)函數(shù)
    onEnd={this.onEnd}//視頻播放結(jié)束時(shí)的回調(diào)函數(shù)
    onAudioBecomingNoisy={this.onAudioBecomingNoisy}//音頻變得嘈雜時(shí)的回調(diào) - 應(yīng)暫停視頻
    onAudioFocusChanged={this.onAudioFocusChanged}//音頻焦點(diǎn)丟失時(shí)的回調(diào) - 如果焦點(diǎn)丟失則暫停
    repeat={false}//確定在到達(dá)結(jié)尾時(shí)是否重復(fù)播放視頻。
/>

ps:這里要注意!
react-native-video通過source屬性設(shè)置視頻,播放遠(yuǎn)程視頻時(shí)使用uri來設(shè)置視頻地址,如下:

source={{uri: "http://www.xxx.com/xxx/xxx/xxx.mp4"}}

復(fù)制代碼播放本地視頻時(shí),使用方式如下:

source={require('../assets/video/turntable.mp4')}

復(fù)制代碼需要注意的是,source屬性不能為空,uri或本地資源是必須要設(shè)置的,否則會(huì)導(dǎo)致app閃退。uri不能設(shè)置為空字符串,必須是一個(gè)具體的地址。

  • 關(guān)于進(jìn)度條
    在render中聲明兩個(gè)量:flexCompleted和flexRemaining,前者表示已經(jīng)播放完成的進(jìn)度,后者表示剩余的進(jìn)度,,這兩個(gè)量分別作為包裹在View中組件的flex屬性的值:
render() {
        const flexCompleted = this.getCurrentTimePercentage() * 100;
        const flexRemaining = (1 - this.getCurrentTimePercentage()) * 100;
        ...  ...
        <View style={styles.progress}>
            <View style={[styles.innerProgressCompleted, {flex: flexCompleted}]}/>
            <View style={[styles.innerProgressRemaining, {flex: flexRemaining}]}/>
        </View>
}
getCurrentTimePercentage() {
        if (this.state.currentTime > 0) {
            return parseFloat(this.state.currentTime) / parseFloat(this.state.duration);
        }
        return 0;
};
  • 點(diǎn)擊事件的處理
    通過點(diǎn)擊組件中的選項(xiàng),我們可以調(diào)節(jié)視頻的音量、播放速率、縮放的樣式等。
    先把布局定義下:
<View style={styles.controls}>
    <View style={styles.generalControls}>
        <View style={styles.rateControl}>
            {this.renderRateControl(0.25)}
            {this.renderRateControl(0.5)}
            {this.renderRateControl(1.0)}
            {this.renderRateControl(1.5)}
            {this.renderRateControl(2.0)}
        </View>

        <View style={styles.volumeControl}>
            {this.renderVolumeControl(0.5)}
            {this.renderVolumeControl(1)}
            {this.renderVolumeControl(1.5)}
        </View>

        <View style={styles.resizeModeControl}>
            {this.renderResizeModeControl('cover')}
            {this.renderResizeModeControl('contain')}
            {this.renderResizeModeControl('stretch')}
        </View>
    </View>

需要重寫三個(gè)方法來填充事件的內(nèi)容:
renderRateControl(rate):設(shè)置播放速率,改方法接收一個(gè)值表示速率的大小,1.0表示正常速率播放。注意:對(duì)于Android的播放器,rate屬性僅在Android6.0或者更高版本中生效。

 renderRateControl(rate) {
        const isSelected = (this.state.rate === rate);

        return (
            <TouchableOpacity onPress={() => {
                this.setState({rate})
            }}>
                <Text style={[styles.controlOption, {fontWeight: isSelected ? 'bold' : 'normal'}]}>
                    {rate}x
                </Text>
            </TouchableOpacity>
        );
    }

renderVolumeControl(volume):該方法接收一個(gè)值作為音量大小,1.0為正常音量

renderVolumeControl(volume) {
        const isSelected = (this.state.volume === volume);

        return (
            <TouchableOpacity onPress={() => {
                this.setState({volume})
            }}>
                <Text style={[styles.controlOption, {fontWeight: isSelected ? 'bold' : 'normal'}]}>
                    {volume * 100}%
                </Text>
            </TouchableOpacity>
        )
    }

renderResizeModeControl(resizeMode):該方法接收的參數(shù)resizeMode有四種模式:
"none"(默認(rèn)) - 不匹配大小
"contain" - 均勻縮放視頻(保持視頻的寬高比),使視頻的尺寸(寬度和高度)等于或小于視圖的相應(yīng)尺寸(減去填充)
"cover" - 均勻縮放視頻(保持視頻的寬高比),使圖像的尺寸(寬度和高度)等于或大于視圖的相應(yīng)尺寸(減去填充)
"stretch" - 獨(dú)立縮放寬度和高度,這可能會(huì)改變src的寬高比

renderResizeModeControl(resizeMode) {
        const isSelected = (this.state.resizeMode === resizeMode);

        return (
            <TouchableOpacity onPress={() => {
                this.setState({resizeMode})
            }}>
                <Text style={[styles.controlOption, {fontWeight: isSelected ? 'bold' : 'normal'}]}>
                    {resizeMode}
                </Text>
            </TouchableOpacity>
        )
    }
  • 最后,重新定義事件屬性onLoad、onEnd、onProgress等
    video: Video;
    onLoad = (data) => {
        this.setState({duration: data.duration});
    };

    onProgress = (data) => {
        this.setState({currentTime: data.currentTime});
    };

    onEnd = () => {
        this.setState({paused: true});
        this.video.seek(0)
    };

    onAudioBecomingNoisy = () => {
        this.setState({paused: true})
    };

    onAudioFocusChanged = (event: { hasAudioFocus: boolean }) => {
        this.setState({paused: !event.hasAudioFocus})
    };

注意一下onEnd的回調(diào)中用到了seek()方法,這個(gè)方法接收的參數(shù)的單位是秒,意味著seek(定位)到由秒表示的指定位置,seek(0)也就是定位到視頻開始播放的位置。

附錄

這樣,一個(gè)可靈活使用的視頻播放器Demo就已經(jīng)做好了,當(dāng)然我們也可以自己定制喜歡的樣式和布局,例如下面這種:

screenshot2

實(shí)現(xiàn)上圖的源碼在這

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,872評(píng)論 25 709
  • 清潔的天 宛如神仙的衣袖拂拭 眼前的城 彌漫昔日的流彩異光 一襲微風(fēng)吹亂端詳?shù)脑?在我心中驚起滔天巨浪 走不進(jìn)的世...
    花苞谷牌干脆面閱讀 318評(píng)論 0 1
  • 晚上6點(diǎn)才下班,到家要清理小黑的屎尿,先用肥皂水拖一遍地去味道,再用清水拖一遍地去肥皂水怕滑倒,接著弄晚飯...
    田心妙閱讀 208評(píng)論 0 1

友情鏈接更多精彩內(nèi)容