init
This commit is contained in:
parent
54dfc1d822
commit
67dce9ddc0
9 changed files with 457 additions and 1 deletions
140
src/helpers/utils.ts
Normal file
140
src/helpers/utils.ts
Normal file
|
@ -0,0 +1,140 @@
|
|||
import { FlacStreamTagger } from "flac-stream-tagger";
|
||||
|
||||
export default class {
|
||||
authHeaders: { [key: string]: string }
|
||||
|
||||
constructor(authHeaders: { [key: string]: string }) {
|
||||
this.authHeaders = authHeaders
|
||||
}
|
||||
|
||||
async fetchTrack(id: number) {
|
||||
const audio = await fetch(`https://api.tidal.com/v1/tracks/${id}/playbackinfopostpaywall/v4?audioquality=HI_RES_LOSSLESS&playbackmode=STREAM&assetpresentation=FULL`, {
|
||||
headers: this.authHeaders
|
||||
})
|
||||
return await audio.json() as {
|
||||
trackId: number,
|
||||
audioPresentation: string,
|
||||
audioMode: string,
|
||||
audioQuality: string,
|
||||
manifestMimeType: string,
|
||||
manifestHash: string,
|
||||
manifest: string,
|
||||
albumReplayGain: number,
|
||||
albumPeakAmplitude: number,
|
||||
trackReplayGain: number,
|
||||
trackPeakAmplitude: number,
|
||||
bitDepth: number,
|
||||
sampleRate: number,
|
||||
}
|
||||
}
|
||||
|
||||
async fetchTracks() {
|
||||
const tracks = await fetch("https://listen.tidal.com/v1/users/199235629/favorites/tracks?offset=0&limit=10000&order=DATE&orderDirection=DESC&countryCode=US", {
|
||||
headers: this.authHeaders
|
||||
})
|
||||
|
||||
return await tracks.json();
|
||||
}
|
||||
|
||||
async downloadFlac(manifestMimeType:string, manifest: string) {
|
||||
const id = Bun.nanoseconds().toString(36);
|
||||
if (manifestMimeType === "application/dash+xml") {
|
||||
await Bun.write(`tmp/${id}.mpd`, Buffer.from(manifest, "base64").toString("utf-8"))
|
||||
|
||||
await Bun.$`mpv --ao=null --stream-record=tmp/${id}.flac --speed=100 tmp/${id}.mpd`.quiet()
|
||||
|
||||
await Bun.file(`tmp/${id}.mpd`).delete();
|
||||
|
||||
const flac = Bun.file(`tmp/${id}.flac`)
|
||||
|
||||
const audioBuffer = await flac.arrayBuffer();
|
||||
|
||||
await flac.delete()
|
||||
|
||||
return audioBuffer;
|
||||
} else if (manifestMimeType === "application/vnd.tidal.bts") {
|
||||
const data = JSON.parse(Buffer.from(manifest, "base64").toString("utf-8")) as {
|
||||
"mimeType": string,
|
||||
"codecs": string,
|
||||
"encryptionType": string,
|
||||
"urls": string[]
|
||||
}
|
||||
|
||||
const flac = await fetch(data.urls[0])
|
||||
|
||||
return await flac.arrayBuffer();
|
||||
}
|
||||
|
||||
return new ArrayBuffer(0);
|
||||
}
|
||||
|
||||
async tagFlac(id: number, audioBuffer: ArrayBuffer) {
|
||||
const trackReq = await fetch(`https://api.tidal.com/v1/tracks/${id}/?countryCode=US`, {
|
||||
headers: this.authHeaders
|
||||
})
|
||||
|
||||
const track = await trackReq.json() as {
|
||||
title: string,
|
||||
replayGain: number,
|
||||
peak: number,
|
||||
streamStartDate: string,
|
||||
trackNumber: number,
|
||||
volumeNumber: number, // discNumber
|
||||
copyright: string,
|
||||
bpm: number,
|
||||
url: string, // comment
|
||||
isrc: string,
|
||||
artists: [
|
||||
{
|
||||
name: string,
|
||||
}
|
||||
],
|
||||
album: {
|
||||
id: number,
|
||||
title: string,
|
||||
cover: string,
|
||||
},
|
||||
};
|
||||
|
||||
const alubmReq = await fetch(`https://api.tidal.com/v1/albums/${track.album.id}/?countryCode=US`, {
|
||||
headers: this.authHeaders
|
||||
})
|
||||
|
||||
const album = await alubmReq.json() as {
|
||||
title: string,
|
||||
numberOfTracks: number,
|
||||
releaseDate: string,
|
||||
cover: string,
|
||||
upc: string,
|
||||
artists: [
|
||||
{
|
||||
name: string,
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
return FlacStreamTagger.fromBuffer(Buffer.from(audioBuffer), {
|
||||
tagMap: {
|
||||
title: track.title,
|
||||
trackNumber: track.trackNumber.toString(),
|
||||
discNumber: track.volumeNumber.toString(),
|
||||
bpm: track.bpm.toString(),
|
||||
date: track.streamStartDate,
|
||||
copyright: track.copyright,
|
||||
REPLAYGAIN_TRACK_GAIN: track.replayGain.toString(),
|
||||
REPLAYGAIN_TRACK_PEAK: track.peak.toString(),
|
||||
comment: track.url,
|
||||
isrc: track.isrc,
|
||||
upc: album.upc,
|
||||
artist: track.artists.map((a) => a.name),
|
||||
album: album.title,
|
||||
albumArtist: album.artists.map((a) => a.name),
|
||||
totalTracks: album.numberOfTracks.toString(),
|
||||
year: album.releaseDate.split("-")[0] || "",
|
||||
},
|
||||
picture: {
|
||||
buffer: Buffer.from(await (await fetch(`https://resources.tidal.com/images/${album.cover.replaceAll("-", "/")}/1280x1280.jpg`)).arrayBuffer()),
|
||||
}
|
||||
}).toBuffer()
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue