getInfo function from ytdl-core can take up to 10s, when user jumps it will call that function again. caching will at least make the subsequent request faster.
probably use node-cache
Example
Expand
let ytdlCache: any = {};
export class ResourceController {
@Get(':id/stream')
async getStream(
@Param('id') id: string,
@Req() req: FastifyRequest,
@Res({ passthrough: true }) reply: FastifyReply,
): Promise {
const headers = req.headers;
const videoUrl = `https://www.youtube.com/watch?v=${id}`;
const time = Date.now();
Logger.log(`Fetching video info for ${videoUrl}`);
// check for cache, return info from it
let info = ytdlCache[id];
if (!info) {
Logger.log(`No cache found for ${videoUrl}`);
// const info = await ytdl.getInfo(videoUrl).catch((e) => {
info = await ytdl.getInfo(videoUrl).catch((e) => {
if (e.message.includes('Video unavailable')) {
throw new NotFoundException(e.message);
}
if (e.message.includes('does not match expected format')) {
throw new BadRequestException(e.message);
}
throw new InternalServerErrorException(e, e.message);
});
ytdlCache[id] = info;
console.log('cache', ytdlCache);
} else {
Logger.log(`Cache found for ${videoUrl}`);
}
Logger.log(`Fetched video info for ${videoUrl} in ${Date.now() - time}ms`);
// Find the best available audio-only format with an mp4 container
const audioFormats = ytdl.filterFormats(info.formats, 'audioonly');
const audioFormat = audioFormats.find(
(format) => format.container === 'mp4',
);
// Get the content length of the chosen format
const contentLength = Number(audioFormat.contentLength);
const range = headers.range || `bytes=0-${contentLength - 1}`;
const [rangeStart, rangeEnd] = range.replace(/bytes=/, '').split('-');
const start = parseInt(rangeStart, 10);
const end = rangeEnd ? parseInt(rangeEnd, 10) : contentLength - 1;
// const end = rangeEnd ? parseInt(rangeEnd, 10) : start + 10000;
const chunksize = end - start + 1;
// Create a readable stream for the requested byte range
// const audioStream = ytdl(videoUrl, {
// quality: 'highestaudio',
// filter: 'audioonly',
// range: { start, end },
// });
const audioStream = ytdl.downloadFromInfo(info, {
format: audioFormat,
});
// .on('data', (chunk) => {});
// Send the appropriate headers for a partial content response
reply.raw.writeHead(206, {
'Content-Range': `bytes ${start}-${end}/${contentLength}`,
'Accept-Ranges': 'bytes',
'Content-Length': chunksize,
'Content-Type': 'audio/mp4',
});
// Pipe the audio stream to the response
return new StreamableFile(audioStream);
}
}
Description
getInfo
function from ytdl-core can take up to 10s, when user jumps it will call that function again. caching will at least make the subsequent request faster.probably use
node-cache
Example
Expand