Experiment to rebuild Diffuse using web applets.
1import { parseBlob, parseFromTokenizer, parseWebStream } from "music-metadata";
2import { contentType } from "@std/media-types";
3import * as URI from "uri-js";
4import * as HTTP_TOKENIZER from "@tokenizer/http";
5import * as RANGE_TOKENIZER from "@tokenizer/range";
6
7import type { TrackStats, TrackTags } from "@applets/core/types";
8import type { Extraction, Urls } from "./types";
9
10// 🛠️
11
12export async function musicMetadataTags({
13 includeArtwork,
14 mimeType,
15 stream,
16 urls,
17}: {
18 includeArtwork?: boolean;
19 mimeType?: string;
20 stream?: ReadableStream;
21 urls?: Urls;
22}): Promise<Extraction> {
23 const uri = urls ? URI.parse(urls.get) : undefined;
24 const pathParts = uri?.path?.split("/");
25 const filename = pathParts?.[pathParts.length - 1];
26
27 let meta;
28
29 if (urls?.get.startsWith("blob:")) {
30 const blob = await fetch(urls.get).then((r) => r.blob());
31 meta = await parseBlob(blob, { skipCovers: !includeArtwork });
32 } else if (urls) {
33 const httpClient = new HTTP_TOKENIZER.HttpClient(urls.head, { resolveUrl: false });
34 httpClient.resolvedUrl = urls.get;
35
36 const tokenizer = await RANGE_TOKENIZER.tokenizer(httpClient);
37
38 meta = await parseFromTokenizer(tokenizer, { skipCovers: !includeArtwork });
39 } else if (stream) {
40 meta = await parseWebStream(stream, { mimeType }, { skipCovers: !includeArtwork });
41 } else {
42 throw new Error("Missing args, need either some urls or a stream.");
43 }
44
45 const stats: TrackStats = {
46 duration: meta.format.duration,
47 };
48
49 const tags: TrackTags = {
50 album: meta.common.album,
51 artist: meta.common.artist,
52 disc: { no: meta.common.disk.no || 1, of: meta.common.disk.of ?? undefined },
53 genre: Array.isArray(meta.common.genre) ? meta.common.genre[0] : meta.common.genre,
54 title: meta.common.title || filename || urls?.head || "Unknown",
55 track: { no: meta.common.track.no || 1, of: meta.common.track.of ?? undefined },
56 year: meta.common.year,
57 };
58
59 return {
60 artwork: includeArtwork ? meta.common.picture : undefined,
61 stats,
62 tags,
63 };
64}