feat: group variants of the same IPTV channel into a logical channel (#9)

Add a channelVariantGrouping service that normalizes channel names
(strips region prefixes and quality tokens) to fingerprint duplicate
stream entries and cluster them under a single logical channel with
quality/source variants. Wire it into the Live TV channel list and
player variant selection, reducing duplicates without destructively
merging streams.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
blomios
2026-10-02 08:25:42 +02:00
parent e1342348d1
commit a7a83a6faa
7 changed files with 349 additions and 131 deletions

View File

@ -1819,11 +1819,18 @@ class VideoPlayer {
if (channels.length === 0) return;
const currentIdx = this.currentChannel
? channels.findIndex(c => c.id === this.currentChannel.id)
? channels.findIndex(c => c.variants.some(variant =>
variant.id === this.currentChannel.id && variant.sourceId === this.currentChannel.sourceId
))
: -1;
const prevIdx = currentIdx <= 0 ? channels.length - 1 : currentIdx - 1;
window.app.channelList.selectChannel({ channelId: channels[prevIdx].id });
const previous = channels[prevIdx];
window.app.channelList.selectChannel({
logicalId: previous.fingerprint,
variantId: previous.preferredVariant.id,
sourceId: previous.preferredVariant.sourceId
});
}
/**
@ -1835,11 +1842,18 @@ class VideoPlayer {
if (channels.length === 0) return;
const currentIdx = this.currentChannel
? channels.findIndex(c => c.id === this.currentChannel.id)
? channels.findIndex(c => c.variants.some(variant =>
variant.id === this.currentChannel.id && variant.sourceId === this.currentChannel.sourceId
))
: -1;
const nextIdx = currentIdx >= channels.length - 1 ? 0 : currentIdx + 1;
window.app.channelList.selectChannel({ channelId: channels[nextIdx].id });
const next = channels[nextIdx];
window.app.channelList.selectChannel({
logicalId: next.fingerprint,
variantId: next.preferredVariant.id,
sourceId: next.preferredVariant.sourceId
});
}
/**