Created
February 26, 2024 05:41
-
-
Save samelie/5c987298c40d5e1faec9293b436ec463 to your computer and use it in GitHub Desktop.
browser code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1. Deploy to Cloudflare workers | |
2. Proxy ytdl-core thru the proxy |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { FFmpeg } from '@ffmpeg/ffmpeg' | |
import { fetchFile, toBlobURL } from '@ffmpeg/util' | |
import ytdl from 'ytdl-core' | |
import './style.css' | |
// https://github.com/darenliang/darenliang.com/blob/3debad5aaeadf6581dfab36f32e5166c01b7739b/misc/ytdl-ffmpeg-demo/main.js | |
// https://github.com/ffmpegwasm/ffmpeg.wasm/blob/main/apps/vue-vite-app/src/components/FFmpegDemo.vue | |
const baseURL = 'https://unpkg.com/@ffmpeg/[email protected]/dist/esm' | |
const ffmpeg = new FFmpeg() | |
// REPLACE this! | |
const WORKER_URL = `https://MY_WORKER.workers.dev` | |
const cleanMemory = () => { | |
console.log('[info] unlinking old data') | |
try { | |
ffmpeg.FS('unlink', 'output.mp3') | |
} catch {} | |
try { | |
ffmpeg.FS('unlink', 'output.mp4') | |
} catch {} | |
} | |
const ytdlOptions = { | |
requestOptions: { | |
maxRetries: 2, | |
backoff: { inc: 200, max: 500 }, | |
transform: (parsed) => { | |
const originURL = parsed.protocol + '//' + parsed.hostname + parsed.path | |
parsed.host = WORKER_URL.split('https://')[1] | |
parsed.hostname = WORKER_URL.split('https://')[1] | |
parsed.path = '/?url=' + encodeURIComponent(originURL) | |
parsed.protocol = 'https:' | |
return parsed | |
}, | |
}, | |
} | |
const proxy = (url) => { | |
return `${WORKER_URL}/?url=` + encodeURIComponent(url) | |
} | |
const getAudioBuffer = async (audioInfo) => { | |
cleanMemory() | |
console.log('[info] fetching data') | |
await ffmpeg.writeFile('test.m4a', await fetchFile(proxy(audioInfo.url))) | |
await ffmpeg.exec(['-i', 'test.m4a', 'output.mp3']) | |
const data = await ffmpeg.readFile('output.mp3') | |
document.getElementById('track').src = URL.createObjectURL( | |
new Blob([(data as Uint8Array).buffer], { type: 'video/mp4' }), | |
) | |
await document.getElementById('track')?.play() | |
} | |
const getBestAudioBuffer = async (url) => { | |
const info = await getInfo(url) | |
console.log('[info] choosing format') | |
const audioInfo = ytdl.chooseFormat(info.formats, { | |
quality: 'highestaudio', | |
filter: 'audioonly', | |
}) | |
return await getAudioBuffer(audioInfo) | |
} | |
const getInfo = async (url) => { | |
console.log('[info] getting info') | |
return await ytdl.getInfo(url, ytdlOptions) | |
} | |
;(async () => { | |
ffmpeg.on('log', ({ message }) => { | |
console.log(message) | |
}) | |
ffmpeg.on('progress', ({ progress, time }) => { | |
console.log(progress) | |
}) | |
await ffmpeg.load({ | |
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'), | |
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'), | |
workerURL: await toBlobURL( | |
`${baseURL}/ffmpeg-core.worker.js`, | |
'text/javascript', | |
), | |
}) | |
getBestAudioBuffer('https://www.youtube.com/watch?v=ui77nVbJZDw').then( | |
(i) => { | |
console.log(i) | |
}, | |
) | |
})() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default { | |
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> { | |
const url = new URL(request.url); | |
const params = new URLSearchParams(url.search); | |
if (!params.has('url')) { | |
return new Response('400 Bad Request', { status: 400 }); | |
} | |
const response = await fetch(decodeURIComponent(params.get('url')), { | |
headers: request.headers, | |
redirect: 'follow', | |
}); | |
const { readable, writable } = new TransformStream(); | |
response.body?.pipeTo(writable); | |
const newResponse = new Response(readable, response); | |
newResponse.headers.append('Access-Control-Allow-Origin', 'http://localhost:5173'); | |
newResponse.headers.append('Access-Control-Allow-Headers', '*'); | |
newResponse.headers.append('Access-Control-Allow-Methods', '*'); | |
return newResponse; | |
}, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment