feat(m3u): extract ClearKey DRM from #KODIPROP playlist lines

Adds the typed ChannelDrm model (shared interfaces) and a KODIPROP
post-processing step in createPlaylistObject() — the single funnel for all
four playlist import paths. Parses inputstream.adaptive.license_type,
license_key and drm_legacy; ClearKey keys accepted as kid:key hex pairs,
W3C ClearKey license JSON, or a plain kid→key JSON map. Unsupported license
types (Widevine/PlayReady/license URLs) are preserved with supported=false
so playback can surface a DRM diagnostic instead of failing silently.
Also adds isDashStreamUrl/isDashChannel helpers for DASH routing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Fable 5 committed 2026-07-18 19:16:25 +02:00
1 parent 643dee1be3
commit e9d336ee7a
12 files changed
+599 -4

No files matched your search

+1
View File
@@ -1,3 +1,4 @@
export * from './lib/channel-drm.interface';
export * from './lib/channel.interface';
export * from './lib/channel.model';
export * from './lib/dev-logger.util';
@@ -0,0 +1,18 @@
/**
* DRM configuration extracted from `#KODIPROP:inputstream.adaptive.*` lines of
* an M3U playlist entry. Only ClearKey is playable in-app; other license types
* are preserved so playback can surface a meaningful DRM diagnostic instead of
* failing silently.
*/
export interface ChannelDrmClearKeys {
/** Key id (32 lowercase hex chars) mapped to its key (32 lowercase hex chars). */
[kidHex: string]: string;
}
export interface ChannelDrm {
/** Normalized license type, e.g. `clearkey` or `com.widevine.alpha`. */
licenseType: string;
/** True only for ClearKey entries with at least one successfully parsed key. */
supported: boolean;
clearKeys?: ChannelDrmClearKeys;
}
@@ -1,3 +1,5 @@
import { ChannelDrm } from './channel-drm.interface';
/**
* Represents channel object
* TODO: define channel interface in iptv-parser library
@@ -29,4 +31,5 @@ export interface Channel {
origin: string;
};
radio: string;
drm?: ChannelDrm;
}
@@ -1,3 +1,5 @@
import { ChannelDrm } from './channel-drm.interface';
export interface ParsedPlaylist {
header: {
attrs: Record<string, string | undefined>;
@@ -31,4 +33,5 @@ export interface ParsedPlaylistItem {
};
timeshift?: string;
radio?: string;
drm?: ChannelDrm;
}
@@ -1,3 +1,4 @@
import { ChannelDrm } from './channel-drm.interface';
import { PlaybackPositionData } from './playback-position.interface';
export interface PlayerContentInfo extends Omit<
@@ -18,4 +19,5 @@ export interface ResolvedPortalPlayback {
userAgent?: string;
referer?: string;
origin?: string;
drm?: ChannelDrm;
}