chore: update public repo

This commit is contained in:
desu-bot 2025-01-18 04:01:14 +00:00
parent 2423324540
commit 090a502ece
No known key found for this signature in database
3 changed files with 335 additions and 40 deletions

View file

@ -1,12 +1,12 @@
import { mkdir, writeFile } from 'node:fs/promises'
import { mkdir, rm, writeFile } from 'node:fs/promises'
import { join } from 'node:path'
import { ffetchAddons } from '@fuman/fetch'
import { asyncPool, base64 } from '@fuman/utils'
import { assert, asyncPool, base64 } from '@fuman/utils'
import { load } from 'cheerio'
import Spinnies from 'spinnies'
import { ProxyAgent } from 'undici'
import { z } from 'zod'
import { $ } from 'zx'
import { $, question } from 'zx'
import { downloadFile, ffetch as ffetchBase } from '../../utils/fetch.ts'
import { sanitizeFilename } from '../../utils/fs.ts'
import { chunks, getEnv } from '../../utils/misc.ts'
@ -133,21 +133,18 @@ async function downloadTrack(track: ScTrack, opts: {
const artworkBytes = track.artwork_url ? new Uint8Array(await ffetchHtml(track.artwork_url).arrayBuffer()) : null
// find the best transcoding
const transcoding = track.media.transcodings.sort((a, b) => {
// prefer non-legacy transcodings
if (a.is_legacy_transcoding && !b.is_legacy_transcoding) return -1
if (!a.is_legacy_transcoding && b.is_legacy_transcoding) return 1
// prefer hq
if (a.quality === 'sq' && b.quality === 'hq') return -1
if (a.quality === 'hq' && b.quality === 'sq') return 1
// prefer opus
if (a.preset === 'opus_0_0' && b.preset !== 'opus_0_0') return -1
if (a.preset !== 'opus_0_0' && b.preset === 'opus_0_0') return 1
return 0
})[0]
let transcoding!: typeof track.media.transcodings[0]
for (const t of track.media.transcodings) {
if (t.quality === 'hq') {
transcoding = t
break
}
if (t.preset === 'opus_0_0') {
transcoding = t
break
}
transcoding = t
}
const { url: hlsUrl } = await ffetchApi(transcoding.url, {
query: {
@ -157,46 +154,55 @@ async function downloadTrack(track: ScTrack, opts: {
url: z.string(),
}))
const ext = transcoding.format.mime_type.match(/^audio\/(\w+)(;|$)/)![1]
let ext = transcoding.format.mime_type.match(/^audio\/(\w+)(;|$)/)![1]
if (ext === 'mp4') ext = 'm4a'
const filename = `${opts.destination}.${ext}`
const params: string[] = [
'-y',
'-i',
hlsUrl,
'-c',
'copy',
]
if (ext === 'mp3') {
if (artworkBytes) {
if (artworkBytes) {
if (ext === 'mp3') {
await writeFile(artworkPath, artworkBytes)
params.push(
'-i',
artworkPath,
'-map',
'0:a',
'1:v:0',
'-id3v2_version',
'3',
'-metadata:s:v',
'title=Album cover',
'-metadata:s:v',
'comment=Cover (front)',
)
} else if (ext === 'ogg') {
const blob = base64.encode(await generateOpusImageBlob(artworkBytes))
params.push(
'-metadata',
`metadata_block_picture=${blob}`,
)
} else if (ext === 'm4a') {
await writeFile(artworkPath, artworkBytes)
params.push(
'-i',
artworkPath,
'-map',
'1:0',
'1',
'-disposition:v',
'attached_pic',
)
}
params.push(
'-id3v2_version',
'3',
'-metadata:s:v',
'title="Album cover"',
'-metadata:s:v',
'comment="Cover (front)"',
)
} else if (ext === 'ogg' && artworkBytes) {
const blob = base64.encode(await generateOpusImageBlob(artworkBytes))
params.push(
'-metadata',
`metadata_block_picture=${blob}`,
)
}
params.push(
'-map',
'0:a',
'-c',
'copy',
'-metadata',
`title=${track.title}`,
'-metadata',
@ -205,6 +211,8 @@ async function downloadTrack(track: ScTrack, opts: {
)
await $`ffmpeg ${params}`.quiet(true)
await rm(artworkPath, { force: true })
}
async function downloadPlaylist(playlist: ScPlaylist) {
@ -259,4 +267,19 @@ async function downloadPlaylist(playlist: ScPlaylist) {
spinnies.stopAll()
}
await downloadPlaylist(await fetchPlaylistByUrl('https://soundcloud.com/user-398958278/sets/l2grace'))
const url = process.argv[2] ?? await question('url > ')
if (!url.startsWith('https://soundcloud.com/')) {
console.error('url must start with https://soundcloud.com/')
process.exit(1)
}
if (url.match(/^https:\/\/soundcloud.com\/[a-z0-9-]+\/sets\//i)) {
await downloadPlaylist(await fetchPlaylistByUrl(url))
} else {
const track = await fetchTrackByUrl(url)
const filename = `${track.user.username}-${track.title}`
console.log('downloading track:', filename)
await downloadTrack(track, {
destination: join('assets/soundcloud-dl', sanitizeFilename(filename)),
})
}