Compare commits

...

2 commits

Author SHA1 Message Date
Pas
6331e69a2f fix quality switching bug 2026-01-08 13:19:21 -07:00
Pas
2f90617eee increase caption delay slider cap 2026-01-08 12:14:00 -07:00
4 changed files with 48 additions and 14 deletions

View file

@ -471,8 +471,8 @@ export function CaptionSettingsView({
</span>
<CaptionDelay
label={t("player.menus.subtitles.settings.delay")}
max={20}
min={-20}
max={40}
min={-40}
onChange={(v) => setDelay(v)}
value={delay}
textTransformer={(s) => `${s}s`}

View file

@ -40,6 +40,7 @@ function useIsIosHls() {
export function QualityView({ id }: { id: string }) {
const router = useOverlayRouter(id);
const isIosHls = useIsIosHls();
const sourceType = usePlayerStore((s) => s.source?.type);
const availableQualities = usePlayerStore((s) => s.qualities);
const currentQuality = usePlayerStore((s) => s.currentQuality);
const switchQuality = usePlayerStore((s) => s.switchQuality);
@ -50,14 +51,18 @@ export function QualityView({ id }: { id: string }) {
const setLastChosenQuality = useQualityStore((s) => s.setLastChosenQuality);
const autoQuality = useQualityStore((s) => s.quality.automaticQuality);
// Auto quality only makes sense for HLS sources
const supportsAutoQuality = sourceType === "hls";
const change = useCallback(
(q: SourceQuality) => {
setLastChosenQuality(q);
setAutomaticQuality(false);
// Don't disable auto quality when manually selecting a quality
// Keep auto quality enabled by default unless user explicitly toggles it
switchQuality(q);
router.close();
},
[router, switchQuality, setLastChosenQuality, setAutomaticQuality],
[router, switchQuality, setLastChosenQuality],
);
const changeAutomatic = useCallback(() => {
@ -90,12 +95,18 @@ export function QualityView({ id }: { id: string }) {
{qualityToString(v)}
</SelectableLink>
))}
<Menu.Divider />
<Menu.Link
rightSide={<Toggle onClick={changeAutomatic} enabled={autoQuality} />}
>
{t("player.menus.quality.automaticLabel")}
</Menu.Link>
{supportsAutoQuality && (
<>
<Menu.Divider />
<Menu.Link
rightSide={
<Toggle onClick={changeAutomatic} enabled={autoQuality} />
}
>
{t("player.menus.quality.automaticLabel")}
</Menu.Link>
</>
)}
<Menu.SmallText>
<Trans
i18nKey={

View file

@ -313,9 +313,24 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
const quality = hlsLevelToQuality(hls.levels[hls.currentLevel]);
emit("changedquality", quality);
} else {
// When automatic quality is disabled, re-lock to preferred quality
// This prevents HLS.js from switching levels unexpectedly
setupQualityForHls();
// When automatic quality is disabled, check if current level matches preferred quality
const currentQuality = hlsLevelToQuality(
hls.levels[hls.currentLevel],
);
const preferredQualityLevel = getPreferredQuality(
hlsLevelsToQualities(hls.levels),
{
lastChosenQuality: preferenceQuality,
automaticQuality: false,
},
);
// Only re-lock if the current level doesn't match our preferred quality
if (currentQuality !== preferredQualityLevel) {
setupQualityForHls();
} else {
// Emit the quality change since we're now at the correct level
emit("changedquality", currentQuality);
}
}
});
hls.on(Hls.Events.SUBTITLE_TRACK_LOADED, () => {

View file

@ -99,7 +99,15 @@ export function selectQuality(
const availableQualities = Object.entries(source.qualities)
.filter((entry) => (entry[1].url.length ?? 0) > 0)
.map((entry) => entry[0]) as SourceQuality[];
const quality = getPreferredQuality(availableQualities, qualityPreferences);
// For file sources (MP4), always use manual quality selection since they don't support switching
const manualQualityPreferences = {
...qualityPreferences,
automaticQuality: false,
};
const quality = getPreferredQuality(
availableQualities,
manualQualityPreferences,
);
if (quality) {
const stream = source.qualities[quality];
if (stream) {