UNPKG

@zezosoft/zezo-ott-react-native-video-player

Version:

Production-ready React Native OTT video player library for Android & iOS. Features: playlists, seasons, auto-next playback, subtitles (SRT/VTT), custom theming, analytics tracking, fullscreen mode, gesture controls, ads player (pre-roll/mid-roll/post-roll

118 lines (94 loc) 3.02 kB
import { useEffect, useState } from 'react'; import axios from 'axios'; import type { MediaTrack } from '../../store/videoPlayer.type'; export interface StreamInfo { bandwidth: number; width: number | string; height: number | string; } async function getHLSBandwidthAndResolutions( m3u8Url: string ): Promise<StreamInfo[]> { try { if (!m3u8Url?.endsWith('.m3u8')) return []; const { data } = await axios.get<string>(m3u8Url); if (!data) return []; const lines = data.split('\n'); const streams: StreamInfo[] = []; let bandwidth: number | null = null; let width: number | null = null; let height: number | null = null; for (const line of lines) { if (line.startsWith('#EXT-X-STREAM-INF')) { const bandwidthMatch = line.match(/BANDWIDTH=(\d+)/); const resolutionMatch = line.match(/RESOLUTION=(\d+)x(\d+)/); bandwidth = bandwidthMatch ? Number(bandwidthMatch[1]) : null; if (resolutionMatch) { width = Number(resolutionMatch[1]); height = Number(resolutionMatch[2]); } } if ( line.trim().endsWith('.m3u8') && bandwidth !== null && width !== null && height !== null ) { streams.push({ bandwidth, width, height }); bandwidth = null; width = null; height = null; } } streams.sort((a, b) => (b.height as number) - (a.height as number)); const autoStream: StreamInfo = { bandwidth: 0, width: 'auto', height: 'auto', }; return [autoStream, ...streams]; } catch (error) { console.error('Error fetching or parsing HLS stream:', error); return []; } } export interface Resolution { height: number | 'auto'; bandwidth: number | null; } const resolutionCache: Record<string, Resolution[]> = {}; export const useVideoResolutions = (track: MediaTrack | null) => { const [resolutions, setResolutions] = useState<Resolution[]>([ { height: 'auto', bandwidth: null }, ]); useEffect(() => { if (!track) return; const source = track.isTrailer ? track.trailerSource : track.sourceLink; if (!source) return; if (resolutionCache[source]) { setResolutions(resolutionCache[source]); return; } const fetchResolutions = async () => { try { const data = await getHLSBandwidthAndResolutions(source); const filteredData = data.filter( (item) => typeof item.height === 'number' ); const newResolutions: Resolution[] = [ { height: 'auto', bandwidth: null }, ...filteredData.map((item) => ({ height: item.height as number, bandwidth: item.bandwidth, })), ]; resolutionCache[source] = newResolutions; setResolutions(newResolutions); } catch (error) { console.error('Failed to fetch video resolutions', error); } }; fetchResolutions(); }, [track]); return resolutions; };