Hi I'm encountering the problem where when i go from my app to other app, and go back not all the time but sometimes, it freezes and also it shows on the screen the icon that the video is not working, the funny thing is that i don't see any error or anything so, what should i do? Anyone with the same problem? I'm using latest expo-video, expo 52 and using flashlist. enter image description here
// video-players.state.ts
import { create } from 'zustand';
import { createVideoPlayer, VideoPlayer } from 'expo-video';
interface VideoPlayerEntry {
player: VideoPlayer;
source: string;
}
interface VideoPlayerMap extends Map<number, VideoPlayerEntry> {}
interface VideoPlayersState {
videoPlayers: VideoPlayerMap;
lastPlayed: number | null;
initializePlayer: (index: number, videoSource: string) => void;
getVideoData: (index: number) => VideoPlayerEntry | undefined;
pauseAllVideos: () => void;
releasePlayer: (index: number) => void;
releaseAllPlayers: () => void;
logAllPlayers: () => void;
handleViewableItemsChanged: ({
viewableItems,
}: {
viewableItems: Array<{ index: number | null }>;
}) => void;
setLastPlayed: (index: number) => void;
}
export const useVideoPlayersStore = create<VideoPlayersState>((set, get) => ({
videoPlayers: new Map(),
lastPlayed: null,
initializePlayer: (index: number, videoSource: string) => {
const videoPlayers = get().videoPlayers;
if (!videoPlayers.has(index)) {
const player = createVideoPlayer(videoSource);
player.loop = true;
player.generateThumbnailsAsync(1);
videoPlayers.set(index, { player, source: videoSource });
set({ videoPlayers: new Map(videoPlayers) });
}
},
getVideoData: (index: number) => {
return get().videoPlayers.get(index);
},
pauseAllVideos: () => {
const videoPlayers = get().videoPlayers;
videoPlayers.forEach((entry, index) => {
if (entry.player.playing) {
entry.player.pause();
set({ lastPlayed: index });
}
});
},
releasePlayer: (index: number) => {
const videoPlayers = get().videoPlayers;
const entry = videoPlayers.get(index);
if (entry) {
if (entry.player.playing) {
entry.player.pause();
}
entry.player.release();
videoPlayers.delete(index);
set({ videoPlayers: new Map(videoPlayers), lastPlayed: null });
}
},
releaseAllPlayers: () => {
const videoPlayers = get().videoPlayers;
videoPlayers.forEach((entry) => {
if (entry.player.playing) {
entry.player.pause();
}
entry.player.release();
});
videoPlayers.clear();
set({ videoPlayers: new Map(), lastPlayed: null });
},
logAllPlayers: () => {
console.log('Logging players:');
get().videoPlayers.forEach((entry, index) => {
console.log(
`Player at index ${index}: ${entry.player.playing ? 'Playing' : 'Paused'}, Source: ${entry.source}`,
);
});
},
handleViewableItemsChanged: ({ viewableItems }) => {
const videoPlayers = get().videoPlayers;
const visibleIndices = viewableItems
.map((item) => item.index)
.filter((i): i is number => i !== null);
let played = false;
videoPlayers.forEach((entry, index) => {
if (visibleIndices.includes(index) && !played) {
if (entry.player) {
entry.player.play();
played = true;
}
} else {
if (entry.player.playing) {
entry.player.pause();
}
}
});
},
setLastPlayed: (index: number) => {
set({ lastPlayed: index });
},
}));
Hi I'm encountering the problem where when i go from my app to other app, and go back not all the time but sometimes, it freezes and also it shows on the screen the icon that the video is not working, the funny thing is that i don't see any error or anything so, what should i do? Anyone with the same problem? I'm using latest expo-video, expo 52 and using flashlist. enter image description here
// video-players.state.ts
import { create } from 'zustand';
import { createVideoPlayer, VideoPlayer } from 'expo-video';
interface VideoPlayerEntry {
player: VideoPlayer;
source: string;
}
interface VideoPlayerMap extends Map<number, VideoPlayerEntry> {}
interface VideoPlayersState {
videoPlayers: VideoPlayerMap;
lastPlayed: number | null;
initializePlayer: (index: number, videoSource: string) => void;
getVideoData: (index: number) => VideoPlayerEntry | undefined;
pauseAllVideos: () => void;
releasePlayer: (index: number) => void;
releaseAllPlayers: () => void;
logAllPlayers: () => void;
handleViewableItemsChanged: ({
viewableItems,
}: {
viewableItems: Array<{ index: number | null }>;
}) => void;
setLastPlayed: (index: number) => void;
}
export const useVideoPlayersStore = create<VideoPlayersState>((set, get) => ({
videoPlayers: new Map(),
lastPlayed: null,
initializePlayer: (index: number, videoSource: string) => {
const videoPlayers = get().videoPlayers;
if (!videoPlayers.has(index)) {
const player = createVideoPlayer(videoSource);
player.loop = true;
player.generateThumbnailsAsync(1);
videoPlayers.set(index, { player, source: videoSource });
set({ videoPlayers: new Map(videoPlayers) });
}
},
getVideoData: (index: number) => {
return get().videoPlayers.get(index);
},
pauseAllVideos: () => {
const videoPlayers = get().videoPlayers;
videoPlayers.forEach((entry, index) => {
if (entry.player.playing) {
entry.player.pause();
set({ lastPlayed: index });
}
});
},
releasePlayer: (index: number) => {
const videoPlayers = get().videoPlayers;
const entry = videoPlayers.get(index);
if (entry) {
if (entry.player.playing) {
entry.player.pause();
}
entry.player.release();
videoPlayers.delete(index);
set({ videoPlayers: new Map(videoPlayers), lastPlayed: null });
}
},
releaseAllPlayers: () => {
const videoPlayers = get().videoPlayers;
videoPlayers.forEach((entry) => {
if (entry.player.playing) {
entry.player.pause();
}
entry.player.release();
});
videoPlayers.clear();
set({ videoPlayers: new Map(), lastPlayed: null });
},
logAllPlayers: () => {
console.log('Logging players:');
get().videoPlayers.forEach((entry, index) => {
console.log(
`Player at index ${index}: ${entry.player.playing ? 'Playing' : 'Paused'}, Source: ${entry.source}`,
);
});
},
handleViewableItemsChanged: ({ viewableItems }) => {
const videoPlayers = get().videoPlayers;
const visibleIndices = viewableItems
.map((item) => item.index)
.filter((i): i is number => i !== null);
let played = false;
videoPlayers.forEach((entry, index) => {
if (visibleIndices.includes(index) && !played) {
if (entry.player) {
entry.player.play();
played = true;
}
} else {
if (entry.player.playing) {
entry.player.pause();
}
}
});
},
setLastPlayed: (index: number) => {
set({ lastPlayed: index });
},
}));
i've had the same issue. Tried a bunch of things and the only thing that helped is switching to expo-av.
Its not maintained anymore but it works for now. We should definitely raise this issue on expo github
I was also facing a similar issue with my looped videos. With expo-video you have a couple options:
option 1:
option 2
Listen to AppState and when entering forground, start you video again.
import { AppState } from "react-native";
useEffect(AppState.addEventListener('change', (nextAppState) => {
switch(nextAppState) {
case 'active':
// Video loop
player.play()
break
default:
break
}
}).remove, [video.playbackTimerSyncedWithVideo])