pstream is dead; long live pstream taciturnaxolotl.github.io/pstream-ng/
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Revert "attempt to fix casting methods"

This reverts commit cca925bf03aacb8e65b408f06b851d23071b7e48.

Pas 29c41270 bbbda4f1

+16 -96
+1 -8
src/components/player/display/base.ts
··· 396 396 containerElement = container; 397 397 }, 398 398 setMeta() {}, 399 - setCaption(caption) { 400 - // If we have a video element and captions are available, 401 - // set up the tracks - AirPlay requires VTT format 402 - if (videoElement && caption && caption.srtData) { 403 - // Subtitles are handled via the track element in VideoContainer.tsx 404 - // convertSubtitlesToObjectUrl already handles the conversion to VTT 405 - } 406 - }, 399 + setCaption() {}, 407 400 408 401 pause() { 409 402 videoElement?.pause();
+15 -88
src/components/player/display/chromecast.ts
··· 7 7 DisplayInterfaceEvents, 8 8 DisplayMeta, 9 9 } from "@/components/player/display/displayInterface"; 10 - import { 11 - convertSubtitlesToObjectUrl, 12 - convertSubtitlesToVtt, 13 - } from "@/components/player/utils/captions"; 14 10 import { LoadableSource } from "@/stores/player/utils/qualities"; 15 11 import { processCdnLink } from "@/utils/cdn"; 16 12 import { ··· 26 22 instance: cast.framework.CastContext; 27 23 } 28 24 25 + /* 26 + ** Chromecasting is unfinished, here is its limitations: 27 + ** 1. Captions - chromecast requires only VTT, but needs it from a URL. we only have SRT urls 28 + ** 2. HLS - we've having some issues with content types. sometimes it loads, sometimes it doesn't 29 + */ 30 + 29 31 export function makeChromecastDisplayInterface( 30 32 ops: ChromeCastDisplayInterfaceOptions, 31 33 ): DisplayInterface { ··· 43 45 title: "", 44 46 type: MWMediaType.MOVIE, 45 47 }; 48 + // eslint-disable-next-line @typescript-eslint/no-unused-vars 46 49 let caption: DisplayCaption | null = null; 47 - let captionUrl: string | null = null; 48 50 49 51 function listenForEvents() { 50 52 const listen = async (e: cast.framework.RemotePlayerChangedEvent) => { ··· 98 100 }; 99 101 } 100 102 101 - function setupCaptions(): chrome.cast.media.Track[] | null { 102 - if (!caption || !caption.srtData) return null; 103 - 104 - try { 105 - // Convert SRT to VTT and create an object URL 106 - captionUrl = convertSubtitlesToObjectUrl(caption.srtData); 107 - 108 - // Create a text track for Chromecast 109 - const track = new chrome.cast.media.Track( 110 - 1, // trackId 111 - chrome.cast.media.TrackType.TEXT, 112 - ); 113 - 114 - track.trackContentId = captionUrl; 115 - track.trackContentType = "text/vtt"; 116 - track.subtype = chrome.cast.media.TextTrackType.SUBTITLES; 117 - track.name = caption.language; 118 - track.language = caption.language; 119 - 120 - return [track]; 121 - } catch (error) { 122 - console.error("Error setting up captions for Chromecast:", error); 123 - return null; 124 - } 125 - } 126 - 127 103 function setupSource() { 128 104 if (!source) { 129 105 ops.controller?.stop(); 130 106 return; 131 107 } 132 108 133 - // Determine correct content type 134 - let contentType = "video/mp4"; 135 - if (source.type === "hls") { 136 - // Use MIME type that's best supported by Chromecast for HLS 137 - contentType = "application/vnd.apple.mpegurl"; 138 - } 109 + let type = "video/mp4"; 110 + if (source.type === "hls") type = "application/x-mpegurl"; 139 111 140 112 const metaData = new chrome.cast.media.GenericMediaMetadata(); 141 113 metaData.title = meta.title; 142 114 143 - // Create media info with proper content ID and content type 144 - const mediaInfo = new chrome.cast.media.MediaInfo( 145 - processCdnLink(source.url), // Use processed URL as the content ID 146 - contentType, 147 - ); 148 - 149 - // The contentUrl property doesn't exist on the type, use properly typed properties instead 115 + const mediaInfo = new chrome.cast.media.MediaInfo("video", type); 116 + (mediaInfo as any).contentUrl = processCdnLink(source.url); 150 117 mediaInfo.streamType = chrome.cast.media.StreamType.BUFFERED; 151 118 mediaInfo.metadata = metaData; 152 119 mediaInfo.customData = { 153 120 playbackRate, 154 121 }; 155 122 156 - // Set up captions if available 157 - const tracks = setupCaptions(); 158 - if (tracks && tracks.length > 0) { 159 - mediaInfo.tracks = tracks; 160 - } 161 - 162 123 const request = new chrome.cast.media.LoadRequest(mediaInfo); 163 124 request.autoplay = true; 164 125 request.currentTime = startAt; 165 126 166 127 if (source.type === "hls") { 167 128 const staticMedia = chrome.cast.media as any; 168 - // Set HLS-specific properties to improve reliability 169 - if (staticMedia.HlsSegmentFormat) { 170 - const media = request.media as any; 171 - media.hlsSegmentFormat = staticMedia.HlsSegmentFormat.FMP4; 172 - media.hlsVideoSegmentFormat = staticMedia.HlsVideoSegmentFormat.FMP4; 173 - // Set additional properties to improve HLS compatibility 174 - media.streamType = chrome.cast.media.StreamType.BUFFERED; 175 - media.hlsPreload = true; 176 - } 129 + const media = request.media as any; 130 + media.hlsSegmentFormat = staticMedia.HlsSegmentFormat.FMP4; 131 + media.hlsVideoSegmentFormat = staticMedia.HlsVideoSegmentFormat.FMP4; 177 132 } 178 133 179 - // Load the media on the Chromecast session 180 134 const session = ops.instance.getCurrentSession(); 181 - if (session) { 182 - session.loadMedia(request).catch((error) => { 183 - console.error("Error loading media on Chromecast:", error); 184 - emit("error", { 185 - message: `Chromecast error: ${error.message || "Failed to load media"}`, 186 - errorName: "ChromecastLoadError", 187 - type: "global", 188 - }); 189 - }); 190 - } 135 + session?.loadMedia(request); 191 136 } 192 137 193 138 function setSource() { ··· 221 166 stopListening(); 222 167 destroyVideoElement(); 223 168 fscreen.removeEventListener("fullscreenchange", fullscreenChange); 224 - // Clean up caption URL object if it exists 225 - if (captionUrl) { 226 - try { 227 - URL.revokeObjectURL(captionUrl); 228 - } catch (e) { 229 - // Ignore errors during cleanup 230 - } 231 - } 232 169 }, 233 170 load(loadOps) { 234 171 source = loadOps.source; ··· 240 177 // cant control qualities 241 178 }, 242 179 setCaption(newCaption) { 243 - // Clean up previous caption URL if it exists 244 - if (captionUrl) { 245 - try { 246 - URL.revokeObjectURL(captionUrl); 247 - captionUrl = null; 248 - } catch (e) { 249 - // Ignore errors during cleanup 250 - } 251 - } 252 - 253 180 caption = newCaption; 254 181 setSource(); 255 182 },