OnBuffer props in react-native-video is not working

Viewed 9647

I am using react-native-video for playing videos from url. I am using onBuffer prop to show loader if the video is buffering. But in my case onBuffer is not working. If the video size is large then in case of a slow network or unstable network video is taking time to play, so I want to show loader if the video is not playing but in buffering mode.

4 Answers

I had same issue and i was able to fix this in android by following this suggestion: https://github.com/react-native-community/react-native-video/issues/1920#issuecomment-604545238

From what i understand, by default android uses android player which dont have these features. But ExoPlayer has lots features like buffering, adaptive bitrate etc.. So, we have to explicitly specify to use ExoPlayer. Important part is to enable multiDex.

This is what the fix suggested and it worked fine:

If you are curois how to enable exoplayer then follow these steps:

create react-native.config.js with following content:

module.exports = {
  dependencies: {
    'react-native-video': {
      platforms: {
        android: {
          sourceDir: '../node_modules/react-native-video/android-exoplayer',
        },
      },
    },
  },
};

now enable multidex following this https://developer.android.com/studio/build/multidex

clean using gradlew clean and rebuild to make it work

You can use onLoad and onEnd prop of react-native-video to show loader.

For Example

<Video
    poster={/*uri*/}
    posterResizeMode="cover"
    source={/*source*/}
    onLoad={()=>/* set loader to true*/}
    onEnd={()=>/* set loader to false*/}
  />

I was doing this all stuff in my application on buffering state you can simply check the state on buffer and display loader like this. You have to use a combination of onLoadStart, onBuffer and onLoadEnd, Below is an example of how you can also build your custom loader and display while buffering. If you don't want to use my loader or this animation stuff remove that thing and render your own loader.

    class VideoPlayer extends React.Component {
       constructor (props) {
       super(props)
       this.state = {
          paused: false,
          buffering: true,
          animated: new Animated.Value(0),
          progress: 0,
          duration: 0
    }
  }
  handleMainButtonTouch = () => {
    if (this.state.progress >= 1) {
      this.player.seek(0)
    }

    this.setState(state => {
      return {
        paused: !state.paused
      }
    })
  };
  handleProgressPress = e => {
    const position = e.nativeEvent.locationX
    const progress = (position / 250) * this.state.duration
    const isPlaying = !this.state.paused

    this.player.seek(progress)
  };

  handleProgress = progress => {
    this.setState({
      progress: progress.currentTime / this.state.duration
    })
  };
  onBuffer = ({isBuffering}) => {
    this.setState({ buffering: isBuffering })
    if (isBuffering) {
      this.triggerBufferAnimation()
    }
    if (this.loopingAnimation && isBuffering) {
      this.loopingAnimation.stopAnimation()
    }
  }
  onLoadStart = () => {
    this.triggerBufferAnimation()
  }

  handleLoad = ({duration}) => {
    this.setState({
      duration: duration
    })
  };

  triggerBufferAnimation = () => {
    this.loopingAnimation && this.loopingAnimation.stopAnimation()
    this.loopingAnimation = Animated.loop(
      Animated.timing(this.state.animated, {
        toValue: 1,
        duration: 1500
      })
    ).start()
  };
  render () {
    console.log('video player ', this.props)
    const { isShowingDetails, hideDetails, showDetails, thumbnailUrl, url } = this.props
    const { buffering } = this.state
    const BufferInterpolation = this.state.animated.interpolate({
      inputRange: [0, 1],
      outputRange: ['0deg', '600deg']
    })
    const rotateStyles = { transform: [{
      rotate: BufferInterpolation
    }]
    }
    return (
      <React.Fragment>
        <Video
          ref={ref => {
            this.player = ref;
          }}
          source={{ uri: url }}
          controls
          paused={this.state.paused}
          // poster={thumbnailUrl}
          onBuffer={this.onBuffer}
          onLoadStart={this.onLoadStart}
          onLoad={this.handleLoad}
          key={url}
          onProgress={this.handleProgress}
          style={styles.backgroundVideo}
          useTextureView={false}
          onVideoEnd={() => alert('Video ended')}
          bufferConfig={{
            minBufferMs: 15000,
            maxBufferMs: 50000,
            bufferForPlaybackMs: 2500,
            bufferForPlaybackAfterRebufferMs: 5000
          }}
        />
        <View
          color={Colors.appColor}
          style={styles.videoCover}
        >{
          buffering && <Animated.View style={rotateStyles}>
            <FontAwesome5 name='circle-notch' size={50} color='rgba(255, 255, 255, 0.6)' />
          </Animated.View>
        }</View>
      </React.Fragment>
    )
  }
}

export default VideoPlayer
const styles = StyleSheet.create({
  backgroundVideo: {
    height: undefined,
    width: '100%',
    backgroundColor: 'black',
    aspectRatio: 16 / 9,
    zIndex: 100
    // 2: 0
  },
  videoCover: {
    justifyContent: 'center',
    alignItems: 'center',
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    backgroundColor: 'transparent',
    zIndex: 10
  },
  controls: {
    backgroundColor: 'rgba(0, 0, 0, 0.5)',
    height: 20,
    left: 0,
    bottom: 5,
    right: 0,
    position: 'absolute',
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-around',
    paddingHorizontal: 10,
    zIndex: 10
  },
  duration: {
    color: '#FFF',
    marginLeft: 15
  }
})

The same happened to me. Solution is to use exoPlayer instead of mediaPlayer. when we install react-native-video package then by default it installs mediaPlayer which is better in case of just working with local media files. But when we need to work with online videos then we need exoPlayer.

How to apply exoPlayer ?

This is well defined in react-native-video docs : https://github.com/react-native-video/react-native-video

Related