diff --git a/src/lib/device-profile.ts b/src/lib/device-profile.ts index 1d67ef4..6ad4f7a 100644 --- a/src/lib/device-profile.ts +++ b/src/lib/device-profile.ts @@ -88,11 +88,13 @@ export function browserDeviceProfile(audioPassthrough = false) { DirectPlayProfiles: [ { - Container: 'mp4,m4v', + // MSE / hls.js can remux these on the fly - no need to force a + // server-side transcode just because the container isn't mp4. + Container: 'mp4,m4v,mkv,avi,mov,wmv,ts,mpeg,mpegts', Type: 'Video', VideoCodec: videoCodecsCsv, AudioCodec: audioPassthrough - ? 'aac,mp3,ac3,eac3,flac,opus,truehd,dts' + ? 'aac,mp3,ac3,eac3,flac,opus,truehd,dts,alac,wmapro' : 'aac,mp3,ac3,eac3,flac,opus', }, { diff --git a/src/pages/PlayerPage.tsx b/src/pages/PlayerPage.tsx index 0bd391d..caf5354 100644 --- a/src/pages/PlayerPage.tsx +++ b/src/pages/PlayerPage.tsx @@ -1091,10 +1091,28 @@ export default function PlayerPage() { hls.startLoad() break case HLS.ErrorTypes.MEDIA_ERROR: - hls.recoverMediaError() + // fragParsingError ("Found no media") means the + // transcoder returned an empty segment - usually a + // cold-start race. Give it a second and retry from + // the current position before doing the heavy + // recoverMediaError reset (which causes a visible skip). + if (data.details === 'fragParsingError') { + const pos = hls.media?.currentTime + setTimeout(() => { + if (hls.destroyed) return + try { + hls.loadSource(hls.url) + if (pos != null && hls.media) { + hls.media.currentTime = pos + } + hls.startLoad() + } catch { hls.recoverMediaError() } + }, 1000) + } else { + hls.recoverMediaError() + } break default: - // Unrecoverable - destroy and let the user retry hls.destroy() break }