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.

Improve thumbnail generation and quality selection

Refactors thumbnail queue to generate 127 evenly distributed thumbnails instead of using a layered approach. Adds a new selectLowestQuality function to consistently select the lowest available video quality for thumbnail extraction, replacing the previous selectQuality usage.

Pas bd491f2d c7dcec25

+53 -20
+53 -20
src/components/player/internals/ThumbnailScraper.tsx
··· 3 3 4 4 import { ThumbnailImage } from "@/stores/player/slices/thumbnails"; 5 5 import { usePlayerStore } from "@/stores/player/store"; 6 - import { LoadableSource, selectQuality } from "@/stores/player/utils/qualities"; 6 + import { 7 + LoadableSource, 8 + SourceQuality, 9 + SourceSliceSource, 10 + } from "@/stores/player/utils/qualities"; 7 11 import { usePreferencesStore } from "@/stores/preferences"; 8 12 import { processCdnLink } from "@/utils/cdn"; 9 13 import { isSafari } from "@/utils/detectFeatures"; 10 14 11 - function makeQueue(layers: number): number[] { 12 - const output = [0, 1]; 13 - let segmentSize = 0.5; 14 - let lastSegmentAmount = 0; 15 - for (let layer = 0; layer < layers; layer += 1) { 16 - const segmentAmount = 1 / segmentSize - 1; 17 - for (let i = 0; i < segmentAmount - lastSegmentAmount; i += 1) { 18 - const offset = i * segmentSize * 2; 19 - output.push(offset + segmentSize); 15 + function makeQueue(thumbnails: number): number[] { 16 + const output = []; 17 + for (let i = 0; i < thumbnails; i += 1) { 18 + output.push(i / (thumbnails - 1)); 19 + } 20 + return output; 21 + } 22 + 23 + function selectLowestQuality(source: SourceSliceSource): LoadableSource { 24 + if (source.type === "hls") return source; 25 + 26 + if (source.type === "file") { 27 + const availableQualities = Object.entries(source.qualities) 28 + .filter((entry) => (entry[1].url.length ?? 0) > 0) 29 + .map((entry) => entry[0]) as SourceQuality[]; 30 + 31 + // Quality sorting by priority (higher number = higher quality) 32 + const qualityPriority: Record<SourceQuality, number> = { 33 + "360": 10, 34 + "480": 20, 35 + "720": 30, 36 + "4k": 35, 37 + "1080": 40, 38 + unknown: 50, // unknown is typically the largest quality 39 + }; 40 + 41 + // Find the lowest quality (smallest priority number) that's available 42 + let lowestQuality: SourceQuality | null = null; 43 + let lowestPriority = Infinity; 44 + 45 + for (const quality of availableQualities) { 46 + const priority = qualityPriority[quality] ?? 0; 47 + if (priority < lowestPriority) { 48 + lowestPriority = priority; 49 + lowestQuality = quality; 50 + } 51 + } 52 + 53 + if (lowestQuality) { 54 + const stream = source.qualities[lowestQuality]; 55 + if (stream) { 56 + return stream; 57 + } 20 58 } 21 - lastSegmentAmount = segmentAmount; 22 - segmentSize /= 2; 23 59 } 24 - return output; 60 + 61 + throw new Error("couldn't select lowest quality"); 25 62 } 26 63 27 64 class ThumnbnailWorker { ··· 114 151 if (!vid) return; 115 152 await this.initVideo(); 116 153 117 - const queue = makeQueue(6); // 7 layers is 63 thumbnails evenly distributed 154 + const queue = makeQueue(127); // 127 thumbnails evenly distributed across the video 118 155 for (let i = 0; i < queue.length; i += 1) { 119 156 if (this.interrupted) return; 120 157 await this.takeSnapshot(vid.duration * queue[i]); ··· 137 174 138 175 const start = useCallback(() => { 139 176 let inputStream = null; 140 - if (source) 141 - inputStream = selectQuality(source, { 142 - automaticQuality: false, 143 - lastChosenQuality: "360", 144 - }); 177 + if (source) inputStream = selectLowestQuality(source); 145 178 // dont interrupt existing working 146 179 if (workerRef.current) return; 147 180 // Allow thumbnail generation when video is loaded and has duration ··· 152 185 addImage, 153 186 }); 154 187 workerRef.current = ins; 155 - ins.start(inputStream.stream); 188 + ins.start(inputStream); 156 189 }, [source, addImage, resetImages, hasPlayedOnce, duration]); 157 190 158 191 const startRef = useRef(start);