Updated: I'm using Expo Managed, expo-av
I’m facing an issue when playing .m3u8 video on IOS device. We are uploading video on s3 bucket and generate .m3u8 video url, at the time we load video, it’s showing as black screen in player and only audio playing. When I tried with android I didn’t have any problem.
This is how I'm doing this:
import React, { Fragment } from 'react'
import { Dimensions, StyleSheet, Text } from 'react-native'
import * as ScreenOrientation from 'expo-screen-orientation'
import { Audio, Video } from 'expo-av'
import PropTypes from 'prop-types'
import isString from 'lodash/isString'
import once from 'lodash/once'
import noop from 'lodash/noop'
import i18n from 'i18n'
import { defaultTextColor, layoutPadding } from 'styles/variables'
const { width: windowWidth } = Dimensions.get('window')
const videoWidth = windowWidth
export default class VideoCard extends React.Component {
videoRef = React.createRef()
presentFullscreenOnce = noop
state = {
error: false,
isBuffering: false,
}
async componentDidMount() {
if (this.videoRef.current) {
this.presentFullscreenOnce = once(this.videoRef.current.presentFullscreenPlayer)
}
await Audio.setAudioModeAsync({ playsInSilentModeIOS: true })
}
onPlaybackStatusUpdate = playbackStatus => {
const { didJustFinish, isBuffering } = playbackStatus
const { shouldPlay } = this.props
if (shouldPlay && !isBuffering) {
this.presentFullscreenOnce()
}
if (didJustFinish === true) {
const { onFinish, id } = this.props
if (this.videoRef.current) {
this.videoRef.current.stopAsync()
this.videoRef.current.dismissFullscreenPlayer()
}
onFinish(id)
}
}
onFullscreenUpdate = async ({ fullscreenUpdate }) => {
if (fullscreenUpdate === 0) {
await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.DEFAULT)
}
if (fullscreenUpdate === 2) {
await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT_UP)
}
}
onError = () => {
const { onFinish, id } = this.props
this.setState(() => ({ error: true }))
onFinish(id)
}
render() {
const {
video: {
urls: { hls },
},
shouldPlay,
description,
} = this.props
const { error } = this.state
return error === false && isString(hls) ? (
<Fragment>
<Video
shouldPlay={shouldPlay}
resizeMode={Video.RESIZE_MODE_CONTAIN}
source={{ uri: hls }}
useNativeControls
style={styles.video}
onPlaybackStatusUpdate={this.onPlaybackStatusUpdate}
onFullscreenUpdate={this.onFullscreenUpdate}
onError={this.onError}
ref={this.videoRef}
/>
{description && <Text style={styles.description}>{description}</Text>}
</Fragment>
) : (
<Text style={styles.description}>
{i18n.t('content:Unfortunately your device is not capable of playing this video')}.
</Text>
)
}
}
const styles = StyleSheet.create({
video: {
width: videoWidth,
height: (videoWidth * 9) / 16,
},
description: {
color: defaultTextColor,
textAlign: 'center',
fontSize: 20,
marginTop: 5,
paddingHorizontal: layoutPadding,
},
})
VideoCard.propTypes = {
video: PropTypes.object,
id: PropTypes.string,
onFinish: PropTypes.func,
description: PropTypes.string,
}
Hope someone can help. Many thanks!