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.

estimate quality for non standard levels

Pas 4509a74a 76124c92

+44 -14
+40 -13
src/components/player/display/base.ts
··· 38 38 2160: "4k", 39 39 }; 40 40 41 + // Define quality thresholds for mapping non-standard resolutions 42 + const qualityThresholds = [ 43 + { minHeight: 1800, quality: "4k" as SourceQuality }, 44 + { minHeight: 800, quality: "1080" as SourceQuality }, 45 + { minHeight: 600, quality: "720" as SourceQuality }, 46 + { minHeight: 420, quality: "480" as SourceQuality }, 47 + { minHeight: 0, quality: "360" as SourceQuality }, 48 + ]; 49 + 41 50 function hlsLevelToQuality(level?: Level): SourceQuality | null { 42 - return levelConversionMap[level?.height ?? 0] ?? null; 43 - } 51 + if (!level?.height) return null; 44 52 45 - function qualityToHlsLevel(quality: SourceQuality): number | null { 46 - const found = Object.entries(levelConversionMap).find( 47 - (entry) => entry[1] === quality, 48 - ); 49 - return found ? +found[0] : null; 53 + // First check for exact matches 54 + const exactMatch = levelConversionMap[level.height]; 55 + if (exactMatch) return exactMatch; 56 + 57 + // For non-standard resolutions, map to closest standard quality 58 + for (const threshold of qualityThresholds) { 59 + if (level.height >= threshold.minHeight) { 60 + return threshold.quality; 61 + } 62 + } 63 + 64 + return "unknown"; // fallback to unknown quality 50 65 } 51 66 52 67 function hlsLevelsToQualities(levels: Level[]): SourceQuality[] { 53 68 return levels 54 69 .map((v) => hlsLevelToQuality(v)) 55 70 .filter((v): v is SourceQuality => !!v); 71 + } 72 + 73 + // Sort levels by quality (height) to ensure we can select the best one 74 + function sortLevelsByQuality(levels: Level[]): Level[] { 75 + return [...levels].sort((a, b) => (b.height || 0) - (a.height || 0)); 56 76 } 57 77 58 78 export function makeVideoElementDisplayInterface(): DisplayInterface { ··· 115 135 116 136 if (!hls) return; 117 137 if (!automaticQuality) { 118 - const qualities = hlsLevelsToQualities(hls.levels); 138 + const sortedLevels = sortLevelsByQuality(hls.levels); 139 + const qualities = hlsLevelsToQualities(sortedLevels); 119 140 const availableQuality = getPreferredQuality(qualities, { 120 141 lastChosenQuality: preferenceQuality, 121 142 automaticQuality, 122 143 }); 123 144 if (availableQuality) { 124 - const levelIndex = hls.levels.findIndex( 125 - (v) => v.height === qualityToHlsLevel(availableQuality), 145 + // Find the best level that matches our preferred quality 146 + const matchingLevels = hls.levels.filter( 147 + (level) => hlsLevelToQuality(level) === availableQuality, 126 148 ); 127 - if (levelIndex !== -1) { 128 - hls.currentLevel = levelIndex; 129 - hls.loadLevel = levelIndex; 149 + if (matchingLevels.length > 0) { 150 + // Pick the highest resolution level for this quality 151 + const bestLevel = sortLevelsByQuality(matchingLevels)[0]; 152 + const levelIndex = hls.levels.indexOf(bestLevel); 153 + if (levelIndex !== -1) { 154 + hls.currentLevel = levelIndex; 155 + hls.loadLevel = levelIndex; 156 + } 130 157 } 131 158 } 132 159 } else {
+4 -1
src/stores/player/utils/qualities.ts
··· 52 52 qualityPreferences.automaticQuality || 53 53 qualityPreferences.lastChosenQuality === null || 54 54 qualityPreferences.lastChosenQuality === "unknown" 55 - ) 55 + ) { 56 + // For automatic quality, select the best available quality 57 + // Sort by our quality preference order and pick the first (best) available 56 58 return sortedQualities.find((v) => availableQualites.includes(v)); 59 + } 57 60 58 61 // get preferred quality - not automatic or unknown 59 62 const chosenQualityIndex = sortedQualities.indexOf(