awslabs / amplify-video

An open source Category Plugin for the AWS Amplify-CLI that makes it easy to deploy live and file based streaming video services and integrate them into your Amplify applications.
https://www.npmjs.com/package/amplify-category-video
Apache License 2.0
267 stars 56 forks source link

Video playback not working #187

Closed vitalbone closed 3 years ago

vitalbone commented 3 years ago

Description

I'm having trouble viewing the videos generated and stored in the S3 output bucket. I was hoping someone would be able to point me in the right direction on how to render our videos.

I have read and reread the troubleshooting guides on Access Denied, CORS errors and working with Signed URLS however our videos are still not rendering.

Here is a video stepping through the various parts of the process but not being able to playback the video in the app. 📹 https://www.loom.com/share/3b4b81d7bda34cc49bcbe2ec3d46e261

Code

React App A replica app of the video uploading and playback using Amplify Video can be found here (as seen in the video). Add your aws-exports & aws-video-exports details and take it for a spin!

Custom token generation I've prefixed public to the videoPath, as suggested by the Access Denied troubleshooting docs.

// amplify/backend/video/[projectname]/custom/vod-helpers/LambdaFunctions/CloudFrontTokenGen/index.js
async function signPath(id) {
  /* use wildcard if no specific file is specified */
  const videoPath = `public/${id}/*`;
  const host = process.env.Host;
  const tobeSigned = url.format({
    protocol: 'https:',
    slashes: true,
    host,
    pathname: videoPath,
  });
  const signedUrl = await sign(tobeSigned);
  const urlParams = signedUrl.replace(`https://${host}/${videoPath}`, '');

  return urlParams;
}

No custom prefix There is no custom prefix in the storage configuration:

AWSS3: {
  bucket: awsVideo.awsInputVideo,
  region: awsExports.aws_project_region,
},

When a video is uploaded, transcoded and placed in the output bucket it seems to have moved through that process correctly. An example video:

If I copy and paste the Object URL into a browser, I see an Access Denied page:

Screen Shot 2021-01-25 at 1 18 23 pm

Also, in some cases, we're also seeing a CORS error appear but I'm not sure if it's related:

Screen Shot 2021-01-25 at 1 01 43 pm

Any help would be greatly appreciated.

vitalbone commented 3 years ago

@wizage Do you have any ideas on how to resolve this? Any suggestions would be a big help. Feels so close to working properly.

vitalbone commented 3 years ago

If I curl a complete URL with the token, eg:

curl https://d3cnnb1fvoj8i7.cloudfront.net/public/fd5d998f-23f0-48ae-ad2a-977cf07d7d26/fd5d998f-23f0-48ae-ad2a-977cf07d7d26.m3u8\?Policy\=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9kM2NubmIxZnZvajhpNy5jbG91ZGZyb250Lm5ldC9wdWJsaWMvZmQ1ZDk5OGYtMjNmMC00OGFlLWFkMmEtOTc3Y2YwN2Q3ZDI2LyoiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE2MTIzMzE1Mzd9fX1dfQ__\&Key-Pair-Id\=APKAIHQQEEVA6AY3NHVQ\&Signature\=KBGlrb\~khC7jpmAyHudTPRmp2myOvAjNKS8\~gWl7RKmM1FADgMS5yj2yBmD0ALgEqtnmHpmPNTeYEQ6\~bfmhZ-lqu33k-JF0QOeCft4yzLcmymWyMj68oIHgeVu\~6LS8NQf7UTEP0Yk64lh7TqTOsgCh1lxCGTqCrF7MKbQSWPahJguFewQg9eOBEWdjECHGBsYOSwMbrBmXz2q2R-eraXH4BDgnKDqMa89URMwllTuDybjamR6qbVU3Nr-fHDKqWZQ96egNTtKxRu1jcsSgV60aod2t8C6JX5qIW\~l54UlVW9n02PjnX9gRM6A-kKBRZx4PUg6OEZ5u7GgmfIwNuQ__

I get back the correct response:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-STREAM-INF:BANDWIDTH=340405,AVERAGE-BANDWIDTH=333386,CODECS="avc1.4d401f,mp4a.40.2",RESOLUTION=1280x720,FRAME-RATE=30.000
fd5d998f-23f0-48ae-ad2a-977cf07d7d26_3000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=280746,AVERAGE-BANDWIDTH=272474,CODECS="avc1.4d401f,mp4a.40.2",RESOLUTION=960x540,FRAME-RATE=30.000
fd5d998f-23f0-48ae-ad2a-977cf07d7d26_1500.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=217077,AVERAGE-BANDWIDTH=215573,CODECS="avc1.77.30,mp4a.40.2",RESOLUTION=768x432,FRAME-RATE=30.000
fd5d998f-23f0-48ae-ad2a-977cf07d7d26_750.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=194016,AVERAGE-BANDWIDTH=192261,CODECS="avc1.77.30,mp4a.40.2",RESOLUTION=640x360,FRAME-RATE=30.000
fd5d998f-23f0-48ae-ad2a-977cf07d7d26_325.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=96409,AVERAGE-BANDWIDTH=96405,CODECS="mp4a.40.2"
fd5d998f-23f0-48ae-ad2a-977cf07d7d26_audio.m3u8

And if the URL is incorrect or incomplete, it returns Access Denied:

<?xml version="1.0" encoding="UTF-8"?><Error><Code>AccessDenied</Code><Message>Access denied</Message></Error>

So it feels like it could be a rendering issue? I have followed the same method the UnicornFlix example uses to pass the token in the beforeRequest method, but maybe I'm doing something wrong:

componentDidMount() {
    videojs.Vhs.xhr.beforeRequest = function (options) {
      options.uri = `${options.uri}${videojs.getAllPlayers()[0].options().token}`;
      return options;
    };
    this.player = videojs(this.videoNode, this.props);
}

Also, I am able to play the video in VLC if I download it.

Getting closer to resolving this but not there yet so would appreciate any help, if possible.

osmarbento-AWS commented 3 years ago

Hi @vitalbone, are you trying to play the videos directly from S3? If that the case, as you configured to use signed URL, you have to request the content to the CloudFront domain instead, you bucket seems to not allow public access directly, which is actually fine and recommendable in terms of security. If you your app is requesting properly the Amazon CloudFront domain, could you share the requested url as per the browser network logs? Also, would be helpful if you could share the rendered player as per GridView-index.jsx in the UnicornFlix example.

Thank you.

vitalbone commented 3 years ago

Hi @osmarbento-AWS, thanks for responding. In answer to your questions:

are you trying to play the videos directly from S3?

No, As you can see here, we're trying to play the videos from CloudFront. Where awsVideo.awsOutputVideo maps to d3cnnb1fvoj8i7.cloudfront.net.

could you share the requested url as per the browser network logs?

Sure, here is part of the request info:

General
    Request URL: https://wr4y6agkxfeuxlzi5n2egnrofy.appsync-api.ap-southeast-2.amazonaws.com/graphql

Response Headers
    access-control-allow-origin: *
    access-control-expose-headers: x-amzn-RequestId,x-amzn-ErrorType,x-amz-user-agent,x-amzn-ErrorMessage,Date,x-amz-schema-version
    content-length: 857
    content-type: application/json;charset=UTF-8
    date: Wed, 03 Feb 2021 22:16:26 GMT
    via: 1.1 c8e9fcb0bdf2652cf4693ca6ef2833ce.cloudfront.net (CloudFront)
    x-amz-cf-id: eQLGcJ4-tntuaDI-BqFEw9-dPWOowyAZW2hJ_0Mnay-MKKH_Z5jfsg==
    x-amz-cf-pop: SYD1-C2
    x-amzn-requestid: bef46c91-d188-4e54-a49c-5fa044f6fce3
    x-cache: Miss from cloudfront

Request Headers
    :authority: wr4y6agkxfeuxlzi5n2egnrofy.appsync-api.ap-southeast-2.amazonaws.com
      :method: POST
      :path: /graphql
      :scheme: https
      accept: application/json, text/plain, */*
      accept-encoding: gzip, deflate, br
      accept-language: en-GB,en-US;q=0.9,en;q=0.8
      authorization: AWS4-HMAC-SHA256 Credential=ASIATOBROJMMFVDK2XGM/20210203/ap-southeast-2/appsync/aws4_request, SignedHeaders=content-type;host;x-amz-date;x-amz-security-token;x-amz-user-agent, Signature=a3f8585df838f024df26d2714b8a94a616c3b86203bf169cdceeee34260eca01
      cache-control: no-cache
      content-length: 207
      content-type: application/json; charset=UTF-8
      origin: http://localhost:3000
      pragma: no-cache
      referer: http://localhost:3000/
      sec-fetch-dest: empty
      sec-fetch-mode: cors
      sec-fetch-site: cross-site
      user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36
      x-amz-date: 20210203T221624Z
      x-amz-security-token: IQoJb3JpZ2luX2VjEA4aDmFwLXNvdXRoZWFzdC0yIkYwRAIgTvbVGHaH3qm2mHXso9SOcs3h/d80jfJVdTYqQHeIlnwCIDtziKz/kS6Jpa17wvo/xdTyBg5GvLjHrxk/HgWw4sASKusECPf//////////wEQABoMMjM2MzI2ODk4NDU2Igw5yWTjto39N9HzP3oqvwQCyW+q8nRv73YBdQ1Ws99D7IwiOF/mooifTmxBMzMNFuoZHZh0dUmWAHS5WssxzTI0Rd0xZx+fknxZnw7SqDb+74ZJMo6zl/iVwYPHXbUcd702loAsDnCjxk0oxfW0o+hkRVyjURnx3ckeA08ZjHPY1WcEvFQIJ6y3qMCzP25xRKfx4uQrZ9yIEhVRc/POP8DV4pe1XqBK3a0ughY/LmdR/S5X1266WYl3flt1RYBhuh0e5xo7qofyYmIHdx+IAjClebmwupZF6FA4FMon2HQOiwcjuhxW0BEdiYCs7FoV5vjkZDxWYP5eZx+Q6ND2EPaBCvGGBcG9hORGs8y9dk412VY3eog8JVmg5jzBro3l9OQEaLNCXgMZBetZp3JDkARVp0DhfqGdO1Ina8X3RjNMWOaoWsIh421mxLJlSv56bCa27bNTE0m6VcyEmuHHlPCpRWzaacZDrwKy2Hr3qj9b1hbHfwWgQwmDXB9XdCII0vd2qHlQlTJm2z3iCvjouyIB5ZV483S6Lvjg5VxDakNLEcEqVmUTIlM/XhahgTFDZ9ZDZAx+tDAx9QWI//e34guIuOnE5j0Lhyr1NQVg2WzKs2nWbkffDodSIiwfIcIW4XXM/OKLt8KACncUkjYvMgOQIwEwF3r8ku7rLcExYKrlamSzRqS3ICxTLcD+PxjDzOVgPLU80vxqn/qEA478atAZYS2uPy71eX5oNtDjwIUMjBv/euhcs3cEYIiYWvJvcJ3vc13XE2Bh5Uw+JIFGqzDUwOyABjqGAj0yP8g+8tevO8zdQ6LjiiYK3Hio4J5hPub2AfseR8GaghkMrrO0xruNMYx4as3yzlZJfDEl3RRGPg7ENSM6vDr5a8J+bRlMmTmqKuMzbX8YVPDmb1pOq6nUQrvnRSp2J1a7nX3Lxg+1Ke1FR+4mZGPbiEEKmtfmPQ7sJzkUbN9LRCn3QEAsRthDW4VuRo7TBuMc4c+5vKw0KCyj5KtgbE8JeE0VLn1hVuDOOO2v8jBQqp6l9Kb3F3loAeLqeSWA2hhtIwLJq9VwwnrkJSyBQIY1xrJRGQ7NxaL14mRMO+60FZcKHEkdVJjelHt2xoDDr8sCa7SZgne/Pn7RlkJVH8I8qfE1XzI=
      x-amz-user-agent: aws-amplify/3.8.6 js

could share the rendered player as per GridView-index.jsx in the UnicornFlix example

osmarbento-AWS commented 3 years ago

Thank you, I meant to ask the request for the m3u8 file. Can you share how that request (for the m3u8) is going out of your browser?

vitalbone commented 3 years ago

Can you share how that request (for the m3u8) is going out of your browser?

Sure thing. The problem is I can't see the request for the .m3u8 file in the Network tab. I have created a video of retrieving and trying to play the video.

📹 https://www.loom.com/share/ef5090e0331e48d68922d45fe8831a7e

osmarbento-AWS commented 3 years ago

image from that picture, it looks like the {videoObjectId} is null. Please print sources out so you can double check this.

console.log('sources', sources);

Then, you can check the value in the Dynamo table and double check your GraphQL schema.

Your player code is rendering fine: image

I've test with the following source / url

sources,
            {
              src: `http://d2qohgpffhaffh.cloudfront.net/HLS/vanlife/withad/sdr_uncage_vanlife_admarker_60sec.m3u8`,
              type: 'application/x-mpegURL',
            }

I hope that helps you to find the solution.

vitalbone commented 3 years ago

@osmarbento-AWS That was it! Here I was thinking it was a video config thing when it was a state management thing all along 🤦‍♂️ Thank you very very much. You've made me an extremely happy man.

https://user-images.githubusercontent.com/5966259/106838915-45417000-66f1-11eb-8352-dae69a62a643.mov