mirror of
https://git.stupid.fish/teidesu/scripts.git
synced 2026-01-12 23:21:08 +11:00
chore: update public repo
This commit is contained in:
parent
ef375d1188
commit
46cf487f04
5 changed files with 229 additions and 26 deletions
|
|
@ -9,8 +9,9 @@ import { z } from 'zod'
|
|||
import { $, ProcessOutput, question } from 'zx'
|
||||
import { downloadFile, ffetch as ffetchBase } from '../../utils/fetch.ts'
|
||||
import { sanitizeFilename } from '../../utils/fs.ts'
|
||||
import { generateOpusImageBlob, pipeIntoProc } from '../../utils/media-metadata.ts'
|
||||
import { chunks, getEnv } from '../../utils/misc.ts'
|
||||
import { generateOpusImageBlob } from '../../utils/media-metadata.ts'
|
||||
import { concatSegments, parseSimpleHls } from '../../utils/mp4-streaming.ts'
|
||||
|
||||
const ffetchApi = ffetchBase.extend({
|
||||
baseUrl: 'https://api-v2.soundcloud.com',
|
||||
|
|
@ -29,6 +30,9 @@ const ffetchApi = ffetchBase.extend({
|
|||
})
|
||||
const ffetchHtml = ffetchBase.extend({
|
||||
baseUrl: 'https://soundcloud.com',
|
||||
retry: {
|
||||
maxRetries: 3,
|
||||
},
|
||||
headers: {
|
||||
Cookie: `oauth_token=${getEnv('SOUNDCLOUD_TOKEN')}`,
|
||||
},
|
||||
|
|
@ -156,7 +160,7 @@ async function downloadTrack(track: ScTrack, opts: {
|
|||
transcoding = t
|
||||
}
|
||||
|
||||
const { url: hlsUrl } = await ffetchApi(transcoding.url, {
|
||||
const { url: mediaUrl } = await ffetchApi(transcoding.url, {
|
||||
query: {
|
||||
track_authorization: track.track_authorization,
|
||||
},
|
||||
|
|
@ -174,14 +178,39 @@ async function downloadTrack(track: ScTrack, opts: {
|
|||
url: z.string(),
|
||||
}))
|
||||
|
||||
let ext = transcoding.format.mime_type.match(/^audio\/(\w+)(;|$)/)![1]
|
||||
if (ext === 'mp4') ext = 'm4a'
|
||||
const ext = {
|
||||
aac_256k: 'm4a',
|
||||
aac_160k: 'm4a',
|
||||
aac_1_0: 'm4a',
|
||||
aac_hq: 'm4a',
|
||||
abr_hq: 'm4a',
|
||||
abr_sq: 'm4a',
|
||||
mp3_0_0: 'mp3',
|
||||
opus_0_0: 'ogg',
|
||||
}[transcoding.preset]
|
||||
if (!ext) {
|
||||
throw new Error(`Unsupported transcoding preset: ${transcoding.preset}`)
|
||||
}
|
||||
const filename = `${opts.destination}.${ext}`
|
||||
|
||||
let stream: ReadableStream | null = null
|
||||
let ffmpegInput: string
|
||||
if (transcoding.format.protocol === 'hls') {
|
||||
const segments = parseSimpleHls(await ffetchHtml(mediaUrl).text())
|
||||
stream = concatSegments({
|
||||
segments,
|
||||
poolSize: 4,
|
||||
fetch: async url => new Uint8Array(await ffetchHtml(url).arrayBuffer()),
|
||||
})
|
||||
ffmpegInput = 'pipe:0'
|
||||
} else {
|
||||
ffmpegInput = mediaUrl
|
||||
}
|
||||
|
||||
const params: string[] = [
|
||||
'-y',
|
||||
'-i',
|
||||
hlsUrl,
|
||||
ffmpegInput,
|
||||
]
|
||||
|
||||
if (artworkBytes) {
|
||||
|
|
@ -228,13 +257,17 @@ async function downloadTrack(track: ScTrack, opts: {
|
|||
'-metadata',
|
||||
`artist=${track.user.username}`,
|
||||
'-metadata',
|
||||
`comment=${track.description ?? ''}`,
|
||||
`comment=${`${track.description ?? ''}\n\nripped from soundcloud (id: ${track.id}, url: ${track.permalink_url})`}`.trimStart(),
|
||||
filename,
|
||||
)
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
await $`ffmpeg ${params}`.quiet(true)
|
||||
const promise = $`ffmpeg ${params}`.quiet(true)
|
||||
if (stream) {
|
||||
await pipeIntoProc(promise, stream)
|
||||
}
|
||||
await promise
|
||||
break
|
||||
} catch (e) {
|
||||
if (!(e instanceof ProcessOutput)) {
|
||||
|
|
|
|||
|
|
@ -9,8 +9,7 @@ import { ffetch as ffetchBase } from '../../utils/fetch.ts'
|
|||
import { sanitizeFilename } from '../../utils/fs.ts'
|
||||
import { pipeIntoProc, runMetaflac, writeIntoProc } from '../../utils/media-metadata.ts'
|
||||
import { getEnv } from '../../utils/misc.ts'
|
||||
import { concatMpdSegments, parseSimpleMpd } from '../../utils/mpd.ts'
|
||||
import { createLibcurlFetch } from '../../utils/temkakit/libcurl.ts'
|
||||
import { concatSegments, parseSimpleMpd } from '../../utils/mp4-streaming.ts'
|
||||
|
||||
const oauthResponse = await ffetchBase('https://auth.tidal.com/v1/oauth2/token', {
|
||||
form: {
|
||||
|
|
@ -192,8 +191,8 @@ async function downloadTrack(options: {
|
|||
]
|
||||
|
||||
const proc = $`ffmpeg ${params}`
|
||||
await pipeIntoProc(proc, concatMpdSegments({
|
||||
mpd: parseSimpleMpd(utf8.decoder.decode(manifest)),
|
||||
await pipeIntoProc(proc, concatSegments({
|
||||
segments: parseSimpleMpd(utf8.decoder.decode(manifest)).segments,
|
||||
fetch: async url => new Uint8Array(await ffetch(url).arrayBuffer()),
|
||||
}))
|
||||
await proc
|
||||
|
|
@ -408,7 +407,7 @@ if ((m = url.match(/\/track\/(\d+)/))) {
|
|||
|
||||
await rm(tmpAlbumCoverPath)
|
||||
} else if ((m = url.match(/\/album\/(\d+)/))) {
|
||||
await downloadAlbum(m[1])
|
||||
await downloadAlbum(Number(m[1]))
|
||||
} else if ((m = url.match(/\/artist\/(\d+)/))) {
|
||||
const withAppearsOn = (await question('include appears on albums? (y/N) > ')).toLowerCase() === 'y'
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue