I am building a video-based app on Expo / React Native, and there is sometimes and sometimes not a lag when the videos are playing.
When there isn't a lag, tapping the screen leads to the next video instantly. When there is a lag, tapping the screen leads to the next video after a few seconds.
I also have a progress bar that indicates the percentage completed of the video (similar to Instagram stories). When there isn't a lag, the progress bar completes right when the video completes. When there is a lag, the progress bar is usually only 75% complete when the video has completed.
Here is a link to my app: https://expo.io/@vaibhavverma9/realtalk
I am trying to figure out why my app goes so slowly sometimes and goes smoothly other times.
I use animated bars for the progress bars, if that helps at all.
function ProgressBarsContainer () {
const width = progressBarWidth();
return (
<View style={homeStyles.progressBarContainer}>
{initAnimatedBars(width)}
</View>
)
}
function initAnimatedBars(width) {
const animatedBars = [];
for (let i = 0; i < currentUserVideoCount; i++){
if(i < videoIndex){
animatedBars.push(
<ProgressBar
progress={1}
width={width}
key={i}
color="#734f96"
unfilledColor="#E6E6FA"
borderColor="#000"
borderRadius={1}
height={3}
/>
)
} else if (i == videoIndex) {
animatedBars.push(
<ProgressBar
key={i}
progress={currentProgress}
width={width}
color="#734f96"
unfilledColor="#E6E6FA"
borderColor="#000"
borderRadius={1}
height={3}
/>
)
} else {
animatedBars.push(
<ProgressBar
progress={0}
width={width}
key={i}
color="#734f96"
unfilledColor="#E6E6FA"
borderColor="#000"
borderRadius={1}
height={3}
/>
)
}
}
return animatedBars;
}
I also render multiple videos at the same time for performance.
import React, { useEffect, useRef, useState } from 'react';
import { Video, Audio } from 'expo-av';
import { View, Animated } from 'react-native';
export default function MultipleVideos(props) {
const renderedGroup = props.limit;
let initialIndex;
let indexLimit;
if (props.first) {
const renderedIndex = Math.round(props.userIndex / renderedGroup);
initialIndex = renderedIndex * renderedGroup;
indexLimit = renderedIndex * renderedGroup + renderedGroup / 2;
} else {
const renderedIndex = Math.floor(props.userIndex / renderedGroup);
initialIndex = renderedIndex * renderedGroup + renderedGroup / 2;
indexLimit = renderedIndex * renderedGroup + renderedGroup;
}
useEffect(() => {
Audio.setAudioModeAsync({
playsInSilentModeIOS: true
});
}, []);
const playingData = {
isMuted: false,
shouldPlay: props.shouldPlay,
playbackObject: props.playbackObject,
_onPlaybackStatusUpdate: props._onPlaybackStatusUpdate,
display: "flex"
}
const nonplayingData = {
isMuted: true,
shouldPlay: false,
playbackObject: null,
_onPlaybackStatusUpdate: null,
display: "none"
}
const renderedVideos = [];
if(props.videoData) {
for(let i = initialIndex; i < indexLimit; i++){
const user = props.videoData.users[i];
if(user){
for (let j = 0; j < user.userVideos.length; j++){
const muxPlaybackId = user.userVideos[j].muxPlaybackId;
const muxPlaybackUrl = 'https://stream.mux.com/' + muxPlaybackId + '.m3u8';
if(props.userIndex == i && props.videoIndex == j){
renderedVideos.push(
<PlayingVideo
key={muxPlaybackId}
playbackObject={playingData.playbackObject}
source={muxPlaybackUrl}
isMuted={playingData.isMuted}
shouldPlay={playingData.shouldPlay}
_onPlaybackStatusUpdate={playingData._onPlaybackStatusUpdate}
display={playingData.display}
/>
)
}
else {
renderedVideos.push(
<PlayingVideo
key={muxPlaybackId}
playbackObject={nonplayingData.playbackObject}
source={muxPlaybackUrl}
isMuted={nonplayingData.isMuted}
shouldPlay={nonplayingData.shouldPlay}
_onPlaybackStatusUpdate={nonplayingData._onPlaybackStatusUpdate}
display={nonplayingData.display}
/>
)
}
}
}
}
return(
<View>
{renderedVideos}
</View>
)
} else {
return null;
}
}
function PlayingVideo({playbackObject, source, isMuted, shouldPlay, _onPlaybackStatusUpdate, display}){
return(
<Video
ref={playbackObject}
source={{uri: source}}
// posterSource={{ uri: posterSource}}
// posterStyle={{ width: '100%', height: '100%', display: display, flex: 1 }}
rate={1.0}
volume={1.0}
isMuted={isMuted}
resizeMode="cover"
usePoster={true}
shouldPlay={shouldPlay}
onPlaybackStatusUpdate={_onPlaybackStatusUpdate}
progressUpdateIntervalMillis={50}
isLooping
style={{ width: '100%', height: '100%', display: display}}
>
</Video>
)
}
Please let me know if there is something that comes to mind that might help improve performance. Thanks :)