playlist-data-engine 1.7.2 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -3
- package/bin/cli.cjs +85 -0
- package/dist/core/parser/TrackExtras.d.ts +150 -1
- package/dist/core/parser/TrackExtras.d.ts.map +1 -1
- package/dist/gateway-CDMPqFEH.js +1320 -0
- package/dist/gateway-DKa45Uz6.cjs +6 -0
- package/dist/gateway.d.ts +3 -1
- package/dist/gateway.d.ts.map +1 -1
- package/dist/gateway.js +1 -1
- package/dist/gateway.mjs +22 -14
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/playlist-data-engine.js +34 -34
- package/dist/playlist-data-engine.mjs +964 -1240
- package/dist/utils/engineDocs.d.ts +33 -0
- package/dist/utils/engineDocs.d.ts.map +1 -0
- package/dist/utils/playlistUtils.d.ts +37 -0
- package/dist/utils/playlistUtils.d.ts.map +1 -1
- package/dist/utils/validators.d.ts +27 -0
- package/dist/utils/validators.d.ts.map +1 -1
- package/docs/DATA_ENGINE_REFERENCE.md +6660 -0
- package/docs/USAGE_IN_OTHER_PROJECTS.md +587 -0
- package/docs/features/AUDIO_ANALYSIS.md +610 -0
- package/docs/features/BEAT_DETECTION.md +5250 -0
- package/docs/features/COMBAT_SYSTEM.md +1632 -0
- package/docs/features/CONTENT_PACKS.md +464 -0
- package/docs/features/CUSTOM_CONTENT.md +603 -0
- package/docs/features/ENEMY_GENERATION.md +1711 -0
- package/docs/features/EQUIPMENT_SYSTEM.md +2279 -0
- package/docs/features/EXTENSIBILITY_GUIDE.md +1106 -0
- package/docs/features/GATEWAY_RESOLUTION.md +725 -0
- package/docs/features/IRL_SENSORS.md +360 -0
- package/docs/features/PLAYLIST_PARSING.md +446 -0
- package/docs/features/PREREQUISITES.md +571 -0
- package/docs/features/ROLLS_AND_SEEDS.md +687 -0
- package/docs/features/XP_AND_STATS.md +1221 -0
- package/llms.txt +33 -0
- package/package.json +9 -2
- package/skills/playlist-data-engine/SKILL.md +69 -0
- package/dist/gateway-DUk4nCao.cjs +0 -1
- package/dist/gateway-DyR4M-uH.js +0 -681
package/README.md
CHANGED
|
@@ -26,6 +26,20 @@ npm install
|
|
|
26
26
|
|
|
27
27
|
</details>
|
|
28
28
|
|
|
29
|
+
### Documentation
|
|
30
|
+
|
|
31
|
+
Full docs ship inside the package — no GitHub trip needed:
|
|
32
|
+
|
|
33
|
+
| Where | What |
|
|
34
|
+
|---|---|
|
|
35
|
+
| `node_modules/playlist-data-engine/docs/` | The whole docs folder, version-matched to your install |
|
|
36
|
+
| `npx playlist-data-engine docs` | List every doc — `npx playlist-data-engine docs <topic>` reads one |
|
|
37
|
+
| `engineHelp()` from the package | Same index, returned as markdown — built for AI agents |
|
|
38
|
+
|
|
39
|
+
**Table of contents:** [Data Engine Reference](docs/DATA_ENGINE_REFERENCE.md) (every function, one row each) · [Usage in Other Projects](docs/USAGE_IN_OTHER_PROJECTS.md) · [Playlist Parsing](docs/features/PLAYLIST_PARSING.md) (tracks, mixes, quality) · [Gateway Resolution](docs/features/GATEWAY_RESOLUTION.md) · [Audio Analysis](docs/features/AUDIO_ANALYSIS.md) · [Beat Detection](docs/features/BEAT_DETECTION.md) — plus the game systems (combat, equipment, XP, sensors, seeds) in `docs/features/`.
|
|
40
|
+
|
|
41
|
+
Building with Claude or another coding agent? `npx playlist-data-engine skill` prints the companion Claude Code skill; `engineHelp('skill')` returns it from inside the package.
|
|
42
|
+
|
|
29
43
|
### The Vision: An Intelligent Music Player
|
|
30
44
|
|
|
31
45
|
The original idea — five years ago — was a music player that goes beyond playing static audio. Think of how the best Nintendo games use dynamic music — different arrangements and mixes depending on what the player does. That's a whole category of experiencing recorded music, but only a handful of games have ever explored it. This engine opens that door for any music. It listens to your tracks and reacts to you — the genre, the mood, the beats, the groove, where you are, what you're doing, the weather outside, the time of day. Every song comes with a character, a combat encounter, a rhythm game chart — all generated from the music itself.
|
|
@@ -54,7 +68,8 @@ The engine is modular — use what you want, ignore the rest. Everything here se
|
|
|
54
68
|
### Playlist Parsing & Data Extraction (Core Feature)
|
|
55
69
|
|
|
56
70
|
- **Serverless Playlist Parser** — Parse Arweave-hosted playlists into clean, structured data with automatic gateway failover via the Ario Wayfinder network
|
|
57
|
-
- **Quick Data Extraction** — One-liners to grab audio URLs, image URLs, track titles, artists, genres, tags, durations, VRM models, and more
|
|
71
|
+
- **Quick Data Extraction** — One-liners to grab audio URLs, image URLs, track titles, artists, genres, tags, durations, VRM models, mixes (`getMixes`, `getMixTracks`), and more
|
|
72
|
+
- **Stems & Alternate Mixes** — Tracks ship stems and alternate mixes (Instrumental, Radio Edit) in metadata: find a mix by name (`findMixByName`), resolve it to a playable URL (`resolveMixUrl`), or swap a parsed track's playback (`selectMix`)
|
|
58
73
|
- **Color Extraction** — K-means color palette extraction from track artwork
|
|
59
74
|
- **Arweave Gateway Manager** — Built-in resilience: automatically races multiple Arweave gateways plus the Ario Wayfinder, caches working gateways, and falls back seamlessly when one fails
|
|
60
75
|
|
|
@@ -357,6 +372,8 @@ The engine runs in both environments. Audio analysis uses the Web Audio API (bro
|
|
|
357
372
|
|----------|---------------|
|
|
358
373
|
| **[DATA_ENGINE_REFERENCE.md](docs/DATA_ENGINE_REFERENCE.md)** | Complete API reference — every type, class, method, and reference table |
|
|
359
374
|
| **[USAGE_IN_OTHER_PROJECTS.md](docs/USAGE_IN_OTHER_PROJECTS.md)** | Integration guide with working code examples for every major feature |
|
|
375
|
+
| **[PLAYLIST_PARSING.md](docs/features/PLAYLIST_PARSING.md)** | Playlist parsing options, track data fields, track extras, alternate mixes, and mix selection |
|
|
376
|
+
| **[GATEWAY_RESOLUTION.md](docs/features/GATEWAY_RESOLUTION.md)** | Arweave gateway resolution, AR.IO Wayfinder failover, IPFS URL utilities |
|
|
360
377
|
| **[AUDIO_ANALYSIS.md](docs/features/AUDIO_ANALYSIS.md)** | Sonic fingerprinting, full timeline, TensorFlow genre/mood classification, pitch detection |
|
|
361
378
|
| **[BEAT_DETECTION.md](docs/features/BEAT_DETECTION.md)** | Beat detection, manual charts, auto chart generation, pitch-based button mapping |
|
|
362
379
|
| **[COMBAT_SYSTEM.md](docs/features/COMBAT_SYSTEM.md)** | Turn-based combat engine, simulations, AI combat, parameter sweeps |
|
|
@@ -364,7 +381,7 @@ The engine runs in both environments. Audio analysis uses the Web Audio API (bro
|
|
|
364
381
|
| **[EQUIPMENT_SYSTEM.md](docs/features/EQUIPMENT_SYSTEM.md)** | Equipment generation, enchanting, set bonuses, stat effects |
|
|
365
382
|
| **[CONTENT_PACKS.md](docs/features/CONTENT_PACKS.md)** | Content pack system, creating custom content packs |
|
|
366
383
|
| **[CUSTOM_CONTENT.md](docs/features/CUSTOM_CONTENT.md)** | Custom races, classes, enemies, equipment, spells |
|
|
367
|
-
| **[
|
|
384
|
+
| **[ROLLS_AND_SEEDS.md](docs/features/ROLLS_AND_SEEDS.md)** | Seeded RNG, dice rolling, deterministic combat simulations |
|
|
368
385
|
| **[XP_AND_STATS.md](docs/features/XP_AND_STATS.md)** | XP sources, leveling, stat strategies, prestige system |
|
|
369
386
|
| **[IRL_SENSORS.md](docs/features/IRL_SENSORS.md)** | Real-world sensor integration, activity bonuses |
|
|
370
387
|
| **[PREREQUISITES.md](docs/features/PREREQUISITES.md)** | Dependencies, environment setup, system requirements |
|
|
@@ -374,7 +391,7 @@ The engine runs in both environments. Audio analysis uses the Web Audio API (bro
|
|
|
374
391
|
|
|
375
392
|
## Project Status
|
|
376
393
|
|
|
377
|
-
- **Version**: 1.
|
|
394
|
+
- **Version**: 1.7.2
|
|
378
395
|
- **TypeScript**: Strict mode
|
|
379
396
|
- **Tests**: 7,205 tests across 183 test files
|
|
380
397
|
- **Module**: Dual ESM/CJS with full type declarations
|
package/bin/cli.cjs
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Docs CLI — `npx playlist-data-engine docs [topic]`
|
|
4
|
+
*
|
|
5
|
+
* Plain CommonJS on purpose: it runs straight from the published tarball
|
|
6
|
+
* with zero dependencies and no build step.
|
|
7
|
+
*/
|
|
8
|
+
const fs = require('node:fs');
|
|
9
|
+
const path = require('node:path');
|
|
10
|
+
|
|
11
|
+
const DOCS_DIR = path.join(__dirname, '..', 'docs');
|
|
12
|
+
const SKILL_PATH = path.join(__dirname, '..', 'skills', 'playlist-data-engine', 'SKILL.md');
|
|
13
|
+
|
|
14
|
+
function collectDocs(dir, prefix = '') {
|
|
15
|
+
const out = [];
|
|
16
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
17
|
+
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
18
|
+
if (entry.isDirectory()) out.push(...collectDocs(path.join(dir, entry.name), rel));
|
|
19
|
+
else if (entry.name.endsWith('.md')) out.push(rel);
|
|
20
|
+
}
|
|
21
|
+
return out.sort();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function topics() {
|
|
25
|
+
return collectDocs(DOCS_DIR).map(rel => ({
|
|
26
|
+
rel,
|
|
27
|
+
slug: rel.replace(/\.md$/i, '').replace(/^features\//, '').toLowerCase(),
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function usage() {
|
|
32
|
+
const list = topics().map(t => ` ${t.slug.padEnd(24)} docs/${t.rel}`).join('\n');
|
|
33
|
+
return [
|
|
34
|
+
'playlist-data-engine — docs reader',
|
|
35
|
+
'',
|
|
36
|
+
'USAGE',
|
|
37
|
+
' npx playlist-data-engine docs List every doc',
|
|
38
|
+
' npx playlist-data-engine docs <topic> Print one doc (slug or file path)',
|
|
39
|
+
' npx playlist-data-engine skill Print the Claude Code skill file',
|
|
40
|
+
'',
|
|
41
|
+
'TOPICS',
|
|
42
|
+
list,
|
|
43
|
+
'',
|
|
44
|
+
'Full docs also ship inside the package: node_modules/playlist-data-engine/docs/',
|
|
45
|
+
].join('\n');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const [command, topic] = process.argv.slice(2);
|
|
49
|
+
|
|
50
|
+
if (!command || ['-h', '--help', 'help'].includes(command)) {
|
|
51
|
+
console.log(usage());
|
|
52
|
+
process.exit(0);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (command === 'skill') {
|
|
56
|
+
try {
|
|
57
|
+
console.log(fs.readFileSync(SKILL_PATH, 'utf8'));
|
|
58
|
+
} catch {
|
|
59
|
+
console.error('Skill file not found in this install (expected skills/playlist-data-engine/SKILL.md).');
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
process.exit(0);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (command !== 'docs') {
|
|
66
|
+
console.error(`Unknown command "${command}".\n\n${usage()}`);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (!topic) {
|
|
71
|
+
console.log(usage());
|
|
72
|
+
process.exit(0);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const all = topics();
|
|
76
|
+
const needle = topic.toLowerCase();
|
|
77
|
+
const hit =
|
|
78
|
+
all.find(t => t.slug === needle) ||
|
|
79
|
+
all.find(t => t.rel.toLowerCase() === needle) ||
|
|
80
|
+
all.find(t => t.slug.startsWith(needle));
|
|
81
|
+
if (!hit) {
|
|
82
|
+
console.error(`No doc matches "${topic}".\n\n${usage()}`);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
console.log(fs.readFileSync(path.join(DOCS_DIR, hit.rel), 'utf8'));
|
|
@@ -6,11 +6,15 @@
|
|
|
6
6
|
*
|
|
7
7
|
* - getTrackMetadata: Full raw parsed metadata passthrough
|
|
8
8
|
* - getTrackExtras: Summary of available stems, mixes, and their conditions
|
|
9
|
+
* - resolveSelectedMix: Which of a track's mixes a playlist entry pinned
|
|
10
|
+
* - findMixByName / getPreferredMixByQuality / getUniqueMixes: Mix lookup & grouping
|
|
11
|
+
* - resolveMixUrl / selectMix: Turn a chosen mix into a playable track
|
|
9
12
|
* - evaluateMixConditions: Evaluate mix conditions against sensor context
|
|
10
13
|
*
|
|
11
14
|
* @module core/parser/TrackExtras
|
|
12
15
|
*/
|
|
13
16
|
import type { EnvironmentalContext } from '../types/Environmental.js';
|
|
17
|
+
import type { PlaylistTrack } from '../types/Playlist.js';
|
|
14
18
|
/** A single stem from the metadata */
|
|
15
19
|
export interface StemInfo {
|
|
16
20
|
name: string;
|
|
@@ -170,6 +174,150 @@ export declare function getTrackExtras(metadata: Record<string, unknown> | null)
|
|
|
170
174
|
* placeholder was, or the name matches no mix on the track
|
|
171
175
|
*/
|
|
172
176
|
export declare function resolveSelectedMix(wrapperMix: unknown, attributes: Record<string, string | number> | null | undefined, mixes: MixInfo[] | undefined): SelectedMixInfo | null;
|
|
177
|
+
/** Options for findMixByName */
|
|
178
|
+
export interface FindMixByNameOptions {
|
|
179
|
+
/** Match names ignoring case and surrounding whitespace (default: true) */
|
|
180
|
+
caseInsensitive?: boolean;
|
|
181
|
+
/** Which master to prefer when several mixes share the name (default: 'lossy', matching the pin flow) */
|
|
182
|
+
prefer?: 'lossy' | 'lossless';
|
|
183
|
+
/**
|
|
184
|
+
* Also match alias spellings and concept names — 'inst' finds 'Instrumental',
|
|
185
|
+
* 'aca' finds 'Acapella', 'vox' finds 'Vocals Only'. Exact names always win.
|
|
186
|
+
* Only applies in case-insensitive mode (default: true)
|
|
187
|
+
*/
|
|
188
|
+
aliases?: boolean;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Find a track's mix by name.
|
|
192
|
+
*
|
|
193
|
+
* Unlike the playlist entry's pin (resolveSelectedMix), which matches names
|
|
194
|
+
* exactly and case-sensitively, this is the tolerant lookup for user-facing
|
|
195
|
+
* choice. Three passes, strictest first: the name as written (modulo case and
|
|
196
|
+
* whitespace), then alias spellings — 'inst' and 'no vocals' find
|
|
197
|
+
* 'Instrumental'; 'aca', 'acap' and 'vox' find 'Acapella'; 'tvmix' and
|
|
198
|
+
* 'tv mix' find 'Karaoke', which is its own concept, never an instrumental —
|
|
199
|
+
* matched as whole words so 'Industrial' never matches 'instrumental'.
|
|
200
|
+
* When several mixes match (a lossy and a lossless master), the quality
|
|
201
|
+
* preference decides.
|
|
202
|
+
*
|
|
203
|
+
* @param mixes - The track's mixes, from getTrackExtras
|
|
204
|
+
* @param name - The mix name to find
|
|
205
|
+
* @param options - Matching and quality-preference options
|
|
206
|
+
* @returns The mix, or null when no mix matches
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* ```ts
|
|
210
|
+
* const extras = getTrackExtras(metadata);
|
|
211
|
+
* const instrumental = findMixByName(extras.mixes, 'instrumental');
|
|
212
|
+
* const strict = findMixByName(extras.mixes, 'Instrumental', { aliases: false });
|
|
213
|
+
* ```
|
|
214
|
+
*/
|
|
215
|
+
export declare function findMixByName(mixes: MixInfo[] | null | undefined, name: string, options?: FindMixByNameOptions): MixInfo | null;
|
|
216
|
+
/**
|
|
217
|
+
* Pick the preferred master among mixes that share one name.
|
|
218
|
+
*
|
|
219
|
+
* A mix name can ship twice — once lossy (mp3) and once lossless (wav/flac).
|
|
220
|
+
* `prefer: 'lossy'` picks the compressed master (the parser's own behavior
|
|
221
|
+
* when resolving a pin), `'lossless'` the high-fidelity one. Mixes without a
|
|
222
|
+
* recognized mime type only win as the last-resort fallback.
|
|
223
|
+
*
|
|
224
|
+
* @param namedMixes - Mixes sharing one name
|
|
225
|
+
* @param prefer - Which quality to prefer (default: 'lossy')
|
|
226
|
+
* @returns The preferred mix, or null when the list is empty
|
|
227
|
+
*/
|
|
228
|
+
export declare function getPreferredMixByQuality(namedMixes: MixInfo[] | null | undefined, prefer?: 'lossy' | 'lossless'): MixInfo | null;
|
|
229
|
+
/** Mixes grouped under one name (e.g. a lossy + lossless pair) */
|
|
230
|
+
export interface MixGroup {
|
|
231
|
+
/** The shared name, in the casing the metadata declares it */
|
|
232
|
+
name: string;
|
|
233
|
+
/** Every mix under this name; the first entry is the display pick */
|
|
234
|
+
mixes: MixInfo[];
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Group a track's mixes by name, collapsing lossy/lossless pairs.
|
|
238
|
+
*
|
|
239
|
+
* The grouping key ignores case and surrounding whitespace, so 'Instrumental'
|
|
240
|
+
* and 'instrumental ' land in one group; the group's name keeps the casing of
|
|
241
|
+
* its first member.
|
|
242
|
+
*
|
|
243
|
+
* @param mixes - The track's mixes, from getTrackExtras
|
|
244
|
+
* @returns One group per distinct mix name, in first-appearance order
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* ```ts
|
|
248
|
+
* for (const group of getUniqueMixes(extras.mixes)) {
|
|
249
|
+
* console.log(`${group.name} (${group.mixes.length} masters)`);
|
|
250
|
+
* }
|
|
251
|
+
* ```
|
|
252
|
+
*/
|
|
253
|
+
export declare function getUniqueMixes(mixes: MixInfo[] | null | undefined): MixGroup[];
|
|
254
|
+
/** Options for resolveMixUrl */
|
|
255
|
+
export interface ResolveMixUrlOptions {
|
|
256
|
+
/** Gateway-resolve the final URL through arweaveGatewayManager (default: true) */
|
|
257
|
+
resolveUrl?: boolean;
|
|
258
|
+
/** Follow a mix whose uri points at a metadata JSON file rather than audio (default: true) */
|
|
259
|
+
followMetadata?: boolean;
|
|
260
|
+
/** Timeout for the metadata fetch, in milliseconds (default: 10000) */
|
|
261
|
+
fetchTimeoutMs?: number;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Resolve a mix to a playable audio URL.
|
|
265
|
+
*
|
|
266
|
+
* The parser returns mix uris as written in the metadata — it never resolves
|
|
267
|
+
* them — so this is the last mile before playback. Mix uris come in three
|
|
268
|
+
* shapes, all handled: direct Arweave/IPFS identifiers and URLs (gateway-
|
|
269
|
+
* resolved), and the standard's metadata-JSON indirection, where a mix's uri
|
|
270
|
+
* points at a metadata file whose audio fields name the actual song (followed
|
|
271
|
+
* one level, per the 721J "Alt Outro" example).
|
|
272
|
+
*
|
|
273
|
+
* @param mix - A mix from getTrackExtras, or a selection from resolveSelectedMix
|
|
274
|
+
* @param options - Resolution options
|
|
275
|
+
* @returns The playable URL, or null when the mix has no uri or resolution failed
|
|
276
|
+
*
|
|
277
|
+
* @example
|
|
278
|
+
* ```ts
|
|
279
|
+
* const url = await resolveMixUrl(findMixByName(extras.mixes, 'Instrumental'));
|
|
280
|
+
* ```
|
|
281
|
+
*/
|
|
282
|
+
export declare function resolveMixUrl(mix: MixInfo | SelectedMixInfo | null | undefined, options?: ResolveMixUrlOptions): Promise<string | null>;
|
|
283
|
+
/** Options for selectMix */
|
|
284
|
+
export interface SelectMixOptions {
|
|
285
|
+
/** Which master to prefer when several mixes share the name (default: 'lossy', matching the pin flow) */
|
|
286
|
+
prefer?: 'lossy' | 'lossless';
|
|
287
|
+
/** Also match alias spellings — 'inst' finds 'Instrumental' (default: true) */
|
|
288
|
+
aliases?: boolean;
|
|
289
|
+
/** Gateway-resolve the resulting audio URLs (default: true) */
|
|
290
|
+
resolveUrl?: boolean;
|
|
291
|
+
/** Follow metadata-JSON mix uris to the song file (default: true) */
|
|
292
|
+
followMetadata?: boolean;
|
|
293
|
+
/** When provided, the chosen mix must currently satisfy its conditions */
|
|
294
|
+
conditionsContext?: EvaluationContext;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Choose which of a track's mixes plays, returning a play-ready track.
|
|
298
|
+
*
|
|
299
|
+
* The consumer-side twin of the playlist entry's pin: the parser repoints a
|
|
300
|
+
* pinned track's audio URLs at the pinned mix at parse time, and this does
|
|
301
|
+
* the same for a user's choice. The input track is never mutated. Name
|
|
302
|
+
* matching is tolerant (case-insensitive, trimmed, aliased — 'inst' finds
|
|
303
|
+
* 'Instrumental'); conditions, when a
|
|
304
|
+
* context is given, must currently pass.
|
|
305
|
+
*
|
|
306
|
+
* @param track - A parsed playlist track (with extras from the parser)
|
|
307
|
+
* @param mixName - The mix to play (e.g. 'Instrumental')
|
|
308
|
+
* @param options - Quality preference, resolution, and condition gating
|
|
309
|
+
* @returns A copy of the track with audio URLs swapped to the mix, or null
|
|
310
|
+
* when the track has no such mix or it is unavailable
|
|
311
|
+
*
|
|
312
|
+
* @example
|
|
313
|
+
* ```ts
|
|
314
|
+
* const playlist = await new PlaylistParser().parse(raw);
|
|
315
|
+
* const track = playlist.tracks[0];
|
|
316
|
+
* const instrumental = await selectMix(track, 'Instrumental', { prefer: 'lossless' });
|
|
317
|
+
* if (instrumental) audio.src = instrumental.audio_url;
|
|
318
|
+
* ```
|
|
319
|
+
*/
|
|
320
|
+
export declare function selectMix(track: PlaylistTrack, mixName: string, options?: SelectMixOptions): Promise<PlaylistTrack | null>;
|
|
173
321
|
/**
|
|
174
322
|
* Evaluate all mixes' conditions against the current context.
|
|
175
323
|
*
|
|
@@ -184,8 +332,9 @@ export declare function resolveSelectedMix(wrapperMix: unknown, attributes: Reco
|
|
|
184
332
|
* @example
|
|
185
333
|
* ```ts
|
|
186
334
|
* const extras = getTrackExtras(metadata);
|
|
335
|
+
* const sensors = new EnvironmentalSensors();
|
|
187
336
|
* const context: EvaluationContext = {
|
|
188
|
-
* environment:
|
|
337
|
+
* environment: await sensors.updateSnapshot(),
|
|
189
338
|
* appState: { playCount: 5, isFavorite: true },
|
|
190
339
|
* };
|
|
191
340
|
* const results = evaluateMixConditions(extras, context);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TrackExtras.d.ts","sourceRoot":"","sources":["../../../src/core/parser/TrackExtras.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"TrackExtras.d.ts","sourceRoot":"","sources":["../../../src/core/parser/TrackExtras.ts"],"names":[],"mappings":"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"}
|