Как транслировать загруженное видео с помощью AWS?

Основная задача - защитить видео от скачивания.

Для этого мы решили настроить потоковое видео с S3.

В проекте есть PHP API и клиент. API генерирует предварительно подписанный URL-адрес, по которому видео должно быть загружено в корзину S3. Затем клиент может запросить видео по URL-адресу CDN. Но с подписанными URL-адресами видео можно скачать с клиента.

Мы нашли подход, когда видео конвертируется в MPEG-DASH с помощью AWS Elemental MediaConverter. Задание для MediaConverter можно создать через API. Затем его следует транслировать через AWS Elemental MediaPackage и CloudFront.

Проблемы следующие:

  • Как понять, когда загрузка видео завершена, чтобы запустить MediaConverter Job?
  • Файл MPEG-DASH имеет манифест .mpd, но для MediaPackage требуется манифест .smil. Как автоматически сгенерировать этот файл из .mpd?

PS Если я где-то ошибаюсь, поправьте меня, пожалуйста.

2 ответа

Как понять, когда загрузка видео завершена, чтобы запустить MediaConverter Job?Этого можно добиться с помощью следующего рабочего процесса

  1. пользователь загружает видео в сегмент папки просмотра в S3
  2. событие s3: PutItem запускает функцию Lambda, которая вызывает MediaConvert для преобразования видео.
  3. Преобразованные видео хранятся в S3 с помощью MediaConvert.

Инструкции высокого уровня, как показано ниже.

  • создайте корзину Amazon S3 для загрузки конвертируемых видео. Пример названия корзины: vod-watchfolder-firstname-lastname

  • создать корзину Amazon S3 для хранения преобразованных видеовыходов из MediaConvert (обеспечивает общедоступное чтение, размещение статических веб-сайтов и CORS)

              <?xml version="1.0" encoding="UTF-8"?>
      <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
      <CORSRule>
          <AllowedOrigin>*</AllowedOrigin>
          <AllowedMethod>GET</AllowedMethod>
          <MaxAgeSeconds>3000</MaxAgeSeconds>
          <AllowedHeader>*</AllowedHeader>
      </CORSRule>
      </CORSConfiguration>
    
  • создать роль IAM для передачи в MediaConvert. Используйте консоль IAM для создания новой роли. Назовите его MediaConvertRole и выберите AWS Lambda в качестве типа роли. Используйте встроенные политики для предоставления разрешений другим ресурсам, необходимым для выполнения лямбда-выражения.

  • Создайте роль IAM для вашей лямбда-функции. Используйте консоль IAM для создания роли. Назовите его VODLambdaRole и выберите AWS Lambda в качестве типа роли. Прикрепите управляемую политику под названием AWSLambdaBasicExecutionRole к этой роли, чтобы предоставить необходимые разрешения CloudWatch Logs. Используйте встроенные политики для предоставления разрешений другим ресурсам, необходимым для выполнения лямбда-выражения.

              {
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Action": [
                      "logs:CreateLogGroup",
                      "logs:CreateLogStream",
                      "logs:PutLogEvents"
                  ],
                  "Resource": "*",
                  "Effect": "Allow",
                  "Sid": "Logging"
              },
              {
                  "Action": [
                      "iam:PassRole"
                  ],
                  "Resource": [
                      "ARNforMediaConvertRole"
                  ],
                  "Effect": "Allow",
                  "Sid": "PassRole"
              },
              {
                  "Action": [
                      "mediaconvert:*"
                  ],
                  "Resource": [
                      "*"
                  ],
                  "Effect": "Allow",
                  "Sid": "MediaConvertService"
              },
              {
                  "Action": [
                      "s3:*"
                  ],
                  "Resource": [
                      "*"
                  ],
                  "Effect": "Allow",
                  "Sid": "S3Service"
              }
          ]
      }
    
  • Создайте лямбда-функцию для преобразования видео. Используйте консоль AWS Lambda, чтобы создать новую функцию Lambda с именем VODLambdaConvert, которая будет обрабатывать запросы API. Используйте предоставленный пример реализации convert.py для кода вашей функции.

              #!/usr/bin/env python
    
      import glob
      import json
      import os
      import uuid
      import boto3
      import datetime
      import random
      from urllib.parse import urlparse
      import logging
    
      from botocore.client import ClientError
    
      logger = logging.getLogger()
      logger.setLevel(logging.INFO)
    
      S3 = boto3.resource('s3')
    
      def handler(event, context):
      '''
      Watchfolder handler - this lambda is triggered when video objects are uploaded to the 
      SourceS3Bucket/inputs folder.
      It will look for two sets of file inputs:
          SourceS3Bucket/inputs/SourceS3Key:
              the input video to be converted
    
          SourceS3Bucket/jobs/*.json:
              job settings for MediaConvert jobs to be run against the input video. If 
              there are no settings files in the jobs folder, then the Default job will be run 
              from the job.json file in lambda environment. 
    
      Ouput paths stored in outputGroup['OutputGroupSettings']['DashIsoGroupSettings']['Destination']
      are constructed from the name of the job settings files as follows:
    
          s3://<MediaBucket>/<basename(job settings filename)>/<basename(input)>/<Destination value from job settings file>
      '''
    
      assetID = str(uuid.uuid4())
      sourceS3Bucket = event['Records'][0]['s3']['bucket']['name']
      sourceS3Key = event['Records'][0]['s3']['object']['key']
      sourceS3 = 's3://'+ sourceS3Bucket + '/' + sourceS3Key
      destinationS3 = 's3://' + os.environ['DestinationBucket']
      mediaConvertRole = os.environ['MediaConvertRole']
      application = os.environ['Application']
      region = os.environ['AWS_DEFAULT_REGION']
      statusCode = 200
      jobs = []
      job = {}
    
      # Use MediaConvert SDK UserMetadata to tag jobs with the assetID 
      # Events from MediaConvert will have the assetID in UserMedata
      jobMetadata = {}
      jobMetadata['assetID'] = assetID
      jobMetadata['application'] = application
      jobMetadata['input'] = sourceS3
    
      try:    
    
          # Build a list of jobs to run against the input.  Use the settings files in WatchFolder/jobs
          # if any exist.  Otherwise, use the default job.
    
          jobInput = {}
          # Iterates through all the objects in jobs folder of the WatchFolder bucket, doing the pagination for you. Each obj
          # contains a jobSettings JSON
          bucket = S3.Bucket(sourceS3Bucket)
          for obj in bucket.objects.filter(Prefix='jobs/'):
              if obj.key != "jobs/":
                  jobInput = {}
                  jobInput['filename'] = obj.key
                  logger.info('jobInput: %s', jobInput['filename'])
    
                  jobInput['settings'] = json.loads(obj.get()['Body'].read())
                  logger.info(json.dumps(jobInput['settings'])) 
    
                  jobs.append(jobInput)
    
          # Use Default job settings in the lambda zip file in the current working directory
          if not jobs:
    
              with open('job.json') as json_data:
                  jobInput['filename'] = 'Default'
                  logger.info('jobInput: %s', jobInput['filename'])
    
                  jobInput['settings'] = json.load(json_data)
                  logger.info(json.dumps(jobInput['settings']))
    
                  jobs.append(jobInput)
    
          # get the account-specific mediaconvert endpoint for this region
          mediaconvert_client = boto3.client('mediaconvert', region_name=region)
          endpoints = mediaconvert_client.describe_endpoints()
    
          # add the account-specific endpoint to the client session 
          client = boto3.client('mediaconvert', region_name=region, endpoint_url=endpoints['Endpoints'][0]['Url'], verify=False)
    
          for j in jobs:
              jobSettings = j['settings']
              jobFilename = j['filename']
    
              # Save the name of the settings file in the job userMetadata
              jobMetadata['settings'] = jobFilename
    
              # Update the job settings with the source video from the S3 event 
              jobSettings['Inputs'][0]['FileInput'] = sourceS3
    
              # Update the job settings with the destination paths for converted videos.  We want to replace the
              # destination bucket of the output paths in the job settings, but keep the rest of the
              # path
              destinationS3 = 's3://' + os.environ['DestinationBucket'] + '/' \
                  + os.path.splitext(os.path.basename(sourceS3Key))[0] + '/' \
                  + os.path.splitext(os.path.basename(jobFilename))[0]                 
    
              for outputGroup in jobSettings['OutputGroups']:
    
                  logger.info("outputGroup['OutputGroupSettings']['Type'] == %s", outputGroup['OutputGroupSettings']['Type']) 
    
                  if outputGroup['OutputGroupSettings']['Type'] == 'FILE_GROUP_SETTINGS':
                      templateDestination = outputGroup['OutputGroupSettings']['FileGroupSettings']['Destination']
                      templateDestinationKey = urlparse(templateDestination).path
                      logger.info("templateDestinationKey == %s", templateDestinationKey)
                      outputGroup['OutputGroupSettings']['FileGroupSettings']['Destination'] = destinationS3+templateDestinationKey
    
                  elif outputGroup['OutputGroupSettings']['Type'] == 'HLS_GROUP_SETTINGS':
                      templateDestination = outputGroup['OutputGroupSettings']['HlsGroupSettings']['Destination']
                      templateDestinationKey = urlparse(templateDestination).path
                      logger.info("templateDestinationKey == %s", templateDestinationKey)
                      outputGroup['OutputGroupSettings']['HlsGroupSettings']['Destination'] = destinationS3+templateDestinationKey
    
                  elif outputGroup['OutputGroupSettings']['Type'] == 'DASH_ISO_GROUP_SETTINGS':
                      templateDestination = outputGroup['OutputGroupSettings']['DashIsoGroupSettings']['Destination']
                      templateDestinationKey = urlparse(templateDestination).path
                      logger.info("templateDestinationKey == %s", templateDestinationKey)
                      outputGroup['OutputGroupSettings']['DashIsoGroupSettings']['Destination'] = destinationS3+templateDestinationKey
    
                  elif outputGroup['OutputGroupSettings']['Type'] == 'DASH_ISO_GROUP_SETTINGS':
                      templateDestination = outputGroup['OutputGroupSettings']['DashIsoGroupSettings']['Destination']
                      templateDestinationKey = urlparse(templateDestination).path
                      logger.info("templateDestinationKey == %s", templateDestinationKey)
                      outputGroup['OutputGroupSettings']['DashIsoGroupSettings']['Destination'] = destinationS3+templateDestinationKey
    
                  elif outputGroup['OutputGroupSettings']['Type'] == 'MS_SMOOTH_GROUP_SETTINGS':
                      templateDestination = outputGroup['OutputGroupSettings']['MsSmoothGroupSettings']['Destination']
                      templateDestinationKey = urlparse(templateDestination).path
                      logger.info("templateDestinationKey == %s", templateDestinationKey)
                      outputGroup['OutputGroupSettings']['MsSmoothGroupSettings']['Destination'] = destinationS3+templateDestinationKey
    
                  elif outputGroup['OutputGroupSettings']['Type'] == 'CMAF_GROUP_SETTINGS':
                      templateDestination = outputGroup['OutputGroupSettings']['CmafGroupSettings']['Destination']
                      templateDestinationKey = urlparse(templateDestination).path
                      logger.info("templateDestinationKey == %s", templateDestinationKey)
                      outputGroup['OutputGroupSettings']['CmafGroupSettings']['Destination'] = destinationS3+templateDestinationKey
                  else:
                      logger.error("Exception: Unknown Output Group Type %s", outputGroup['OutputGroupSettings']['Type'])
                      statusCode = 500
    
              logger.info(json.dumps(jobSettings))
    
              # Convert the video using AWS Elemental MediaConvert
              job = client.create_job(Role=mediaConvertRole, UserMetadata=jobMetadata, Settings=jobSettings)
    
      except Exception as e:
          logger.error('Exception: %s', e)
          statusCode = 500
          raise
    
      finally:
          return {
              'statusCode': statusCode,
              'body': json.dumps(job, indent=4, sort_keys=True, default=str),
              'headers': {'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'}
          }
    
  • Обязательно сконфигурируйте свою функцию для использования роли IAM VODLambdaRole, которую вы создали в предыдущем разделе.

  • Создайте триггер события S3 для лямбда-выражения Convert. Используйте консоль AWS Lambda, чтобы добавить триггер putItem из корзины S3 vod-watchfolder-firstname-lastname в лямбда-выражение VODLambdaConvert.

  • протестировать автоматизацию папки наблюдения. Вы можете использовать собственное видео или видео test.mp4, находящееся в этой папке, для тестирования рабочего процесса.

  • Подробнее см. В этом документе https://github.com/aws-samples/aws-media-services-vod-automation/blob/master/MediaConvert-WorkflowWatchFolderAndNotification/README-tutorial.md.

Файл MPEG-DASH имеет манифест .mpd, но для MediaPackage требуется манифест .smil. Как автоматически сгенерировать этот файл из .mpd?

Как понять, когда загрузка видео завершена, чтобы запустить MediaConverter Job?

Я предлагаю вам прочитать эту статью, в которой показано, как автоматизировать рабочий процесс с помощью S3 и лямбда для запуска задания : медиа-преобразованияGitHub: aws-samples / aws-media-services-vod-automation

Файл MPEG-DASH имеет манифест .mpd, но для MediaPackage требуется манифест .smil. Как автоматически сгенерировать этот файл из .mpd?

Можно ли использовать изменение вывода mediaconvert в HLS и передачу в Mediapackage, а затем преобразовать вывод в MPEG-DASH клиенту? В этой статье показано, как настроить эту часть: GitHub: aws-samples / aws-media-services-simple-vod-workflow.

В противном случае вам необходимо создать файл SMIL - AWS Elemental MediaPackage.

Другие вопросы по тегам