При передаче фильма из S3 файл не доступен для поиска - PullRequest
0 голосов
/ 08 января 2019

У нас есть приложение, которое иногда обслуживает файл MP4, который хранится на S3, поскольку каждый конкретный файл должен видеть только конкретный человек, а внутри нашего сервиса мы будем показывать его только авторизованным людям.

Фильм начинает воспроизводиться правильно (во встроенном в браузер теге video), однако, если мы ищем точку в фильме, которая еще не была буферизована, проигрыватель немного буферизуется, а затем прекращает воспроизведение. После нажатия Воспроизвести фильм начнется с начала. Если я сделаю файл общедоступным и получу к нему доступ напрямую из S3, поиск в небуферизованной точке будет работать правильно.

Я создал автономную программу узла, которая воспроизводит эту проблему. Я попытался сделать заголовки ответа идентичными заголовкам, которые посылает S3, но проблема остается.

const http = require("http");
const AWS = require("aws-sdk");
const proxy = require("proxy-agent");

Object.assign(process.env, {
    AWS_ACCESS_KEY_ID: "REDACTED",
    AWS_SECRET_ACCESS_KEY: "REDACTED",
    AWS_EC2_REGION: "us-west-2"
});

const s3 = new AWS.S3({
    s3ForcePathStyle: 'true',
    signatureVersion: 'v4',
    httpOptions: { timeout: 300000 },
    endpoint: 'https://s3.us-west-2.amazonaws.com',
    region: 'us-west-2'
});

const objectParams = {
    Bucket: 'REDACTED',
    Key: 'some-movie.mp4'
};

let request = 0;

function serve(req, res) {
    console.log("Handling request", ++request, req.url);

    s3.headObject(objectParams, (err, data) => {
        if (err)
            throw err;

        const { ContentType: type, ContentLength: length} = data;
        console.log("Got", data);
        if (data.ETag)
            res.setHeader("ETag", data.ETag);

        const range = req.headers.range;
        if (range) {
            console.log("Serving range", range);
            const parts = range.replace("bytes=", "").split("-");
            const start = parseInt(parts[0], 10);
            const end = parts[1]? parseInt(parts[1], 10): length -1;
            let headers  = {
                "Content-Range": `bytes ${start}-${end}/${length}`,
                "Accept-Ranges": "bytes",
                "Content-Type": type,
                "Content-Length": end - start + 1,
                "Last-Modified": data.LastModified,
             };

             if (req.headers["if-range"]) {
                 console.log("Setting if-range to", req.headers["if-range"]);
                 headers["If-Range"] = req.headers["if-range"];
             }

            res.writeHead(206, headers);
        }
        else {
            console.log("Whole file");
            res.setHeader("Accept-Ranges", "bytes");
            res.setHeader("Content-Type", type);
            res.setHeader("Content-Length", length);
            res.setHeader("Last-Modified", data.LastModified);
        }

        const stream = s3.getObject(objectParams).createReadStream();

        stream.on("error", err => console.error("stream error:", err));
        stream.pipe(res).on("finish", data => {
            console.log("Finished streaming");
        });
    });
}

http.createServer(serve).listen(1234);

Чего мне не хватает?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...