Braiden Parkinson
Braiden Parkinson

Reputation: 59

Byte range requests from aws S3

guys so I have a problem consistently and reliably seeking videos with HTML5. I am getting the videos from an AWS S3 Bucket using Nodejs all videos are in mp4 format. I have tried multiple things to get the video's current time to move every time (most of the time it works but occasionally it doesn't move) but to no avail. Heres my code:

router.get("/*", (req, res, next) => {
    let params = {
      Bucket: "bucketName",
      Key: decodeURIComponent(req.path.substring(1))
    };

    s3.getObject(params, function(err, data) {
      if (err) {
        res.status(500).send(err);
      } else {
        res.contentType(data.ContentType);
        res.send(data.Body);
      }
    });
  });
}

I've been doing some reading and people are saying you can use byte-range requests and request the whole video through a byte-range request. This guy seems to do it with a local file but I am at a loss about how to do it with an s3 file. See post: can't seek html5 video or audio in chrome. The other suggestion I've heard of people doing is HLS encoding but I am not sure what is the best way or how to implement them can someone point me in the right direction?

Upvotes: 0

Views: 3766

Answers (1)

jarmod
jarmod

Reputation: 78823

I think the best answer is probably to implement an HLS or DASH streaming solution. Here is an example of HLS with S3 and CloudFront. And here is a more comprehensive Best Practices for Streaming Media Delivery.

Right now, your app server is simply reading the entire video file from S3 and then sending the entire video file contents directly to the client in an HTTP response. While it appears to work, it might be better to avoid proxying this content, and instead serve it directly to the client from S3 (or CloudFront). One way to do that, for private content, is to send the client an S3 pre-signed URL.

I tested a simple HTML5 video web page against an S3-hosted MPEG video file and was able to view it fine on Chrome, as well as seek back and forth at will. I tested with a relatively small MPEG (15MB).

<html>
<body>
    <h1>Stack Overflow 65796272 Video Sample</h1>
    <p>This video and associated poster are sourced from Amazon S3 via pre-signed URL.</p>
    <div id="container">
      <video id='video' controls="controls" preload='none' width="600" poster="https://poster-presigned-url-here">
        <source id='mp4' src="https://video-presigned-url-here" type='video/mp4' />
        <p>Your user agent does not support the HTML5 video element.</p>
      </video>
    </div>
</body>
</html>

I pre-created the poster and video pre-signed URLs using the awscli, but you can do this using an AWS SDK and serve them dynamically to your client (or inject them into the HTML sent to the client using any standard template engine such as Express.js). You can remove the poster, if not needed. Note that pre-signed URLs are time-limited.

Upvotes: 2

Related Questions