Skip to content

Commit

Permalink
fix: fix unseekable videos on webkit-based browsers
Browse files Browse the repository at this point in the history
this commit fixes videos not being able to fast-forward/rewind for lack of http headers and 206
status code

fix #26
  • Loading branch information
zyachel committed Jan 14, 2023
1 parent cfa8c53 commit a32785c
Showing 1 changed file with 25 additions and 2 deletions.
27 changes: 25 additions & 2 deletions src/pages/api/media_proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@ import { NextApiRequest, NextApiResponse } from 'next';
import redis from '../../utils/redis';
import axiosInstance from '../../utils/axiosInstance';

const getCleanReqHeaders = (headers: NextApiRequest['headers']) => ({
...(headers.accept && { accept: headers.accept }),
...(headers.range && { range: headers.range }),
...(headers['accept-encoding'] && {
'accept-encoding': headers['accept-encoding'] as string,
}),
});

const resHeadersArr = [
'content-range',
'content-length',
'content-type',
'accept-ranges',
];

// checks if a url is pointing towards a video/image from imdb
const regex =
/^https:\/\/((m\.)?media-amazon\.com|imdb-video\.media-imdb\.com).*\.(jpg|jpeg|png|mp4|gif|webp).*$/;

Expand All @@ -11,6 +27,7 @@ export default async function handler(
) {
try {
const mediaUrl = req.query.url as string | undefined;
const requestHeaders = getCleanReqHeaders(req.headers);

// 1. returning if query is illegal
if (!mediaUrl || !regex.test(mediaUrl))
Expand All @@ -23,9 +40,15 @@ export default async function handler(
if (redis === null) {
const mediaRes = await axiosInstance.get(mediaUrl, {
responseType: 'stream',
headers: requestHeaders,
});

res.setHeader('Content-Type', mediaRes.headers['content-type']);
// chromium browsers want a 206 response with specific headers. so, we gotta pass them on.
res.statusCode = mediaRes.status;
resHeadersArr.forEach(key => {
const val = mediaRes.headers[key];
if (val) res.setHeader(key, val);
});
mediaRes.data.pipe(res);
return;
}
Expand All @@ -44,7 +67,7 @@ export default async function handler(
responseType: 'arraybuffer',
});

const data = mediaRes.data;
const { data } = mediaRes;

// saving in redis for 30 minutes
await redis!.setex(mediaUrl, 30 * 60, Buffer.from(data));
Expand Down

0 comments on commit a32785c

Please sign in to comment.