视频网站的存储与媒体处理方案

更新时间: 2024-05-20 10:36:11

手动部署

150

https://www.aliyun.com/solution/tech-solution/vsaps

方案概览

视频存储与处理是指基于阿里云服务提供高可靠存储和实时自动化服务,能够满足用户对视频存储、转码、截图、播放、直播等功能的需求。本技术解决方案以搭建一个视频存储和处理服务为例,为您演示:

  • 如何搭建一个视频存储和处理服务。

  • 观察添加水印后的视频。

方案架构

方案提供的默认设置完成部署后在阿里云上搭建的网站运行环境如下图所示。实际部署时您可以根据资源规划修改部分设置,但最终形成的运行环境与下图相似。

1.jpeg

本方案的技术架构包括以下基础设施和云服务:

  • 2个云服务器ECS:部署上传和下载视频网站服务。

  • 1个负载均衡ALB:对外提供访问并将用户请求分配到不同云服务器ECS上的博客网站服务。

  • 1个专有网络VPC:为应用型负载均衡ALB、云服务器ECS等云资源形成云上私有网络。

  • 2台交换机:将2台云服务器ECS连接在同一网络上,实现它们之间的通信,并提供基本的网络分段和隔离功能。

  • 视频点播VOD:将客户端上传视频的消息推送到MNS。

  • 消息服务MNS:接收VOD推送的消息并将其发送给FC。

  • 函数计算FC:收到客户端上传视频的消息后,调用函数从Bucket中获取视频并处理,然后将其上传到另一个Bucket。

  • 对象存储OSS:1个Bucket作为视频点播服务的存储服务,用于存储客户端上传的视频,另1个Bucket用于存储处理后的视频。

  • 2个RAM角色:1个RAM角色用于云服务ECS获取STS临时访问凭证,另一个RAM角色用于视频上传服务获取STS临时访问凭证并上传视频到VOD。

部署准备

10

开始部署前,请按以下指引完成账号申请、账号充值、RAM用户创建和授权。

准备账号

  1. 如果您还没有阿里云账号,请访问阿里云账号注册页面,根据页面提示完成注册。阿里云账号是您使用云资源的付费实体,因此是部署方案的必要前提。

  2. 开通以下云服务:MNSOSSVODFCEventBridge

    说明
    • 因为本方案中的FC Trigger依赖EventBridge,所以您还需要开通EventBridge。

    • 如果点开MNS链接提示开通报错,说明已经开通,您可以直接登录MNS控制台进行确认。

  3. 完成一键授权:AliyunVODDefaultRoleAliyunFCServerlessDevsRole

  4. 为阿里云账号充值

    1. 为节省成本,本方案默认全部选择使用按量付费资源,使用按量付费资源需要确保账户余额不小于100元。

    2. 完成本方案的部署及体验,预计产生费用不超过5元(假设您选择最低规格资源,且资源运行时间不超过30分钟。实际情况中可能部分实例无法购买需要根据实际情况调整资源规格,同时因您操作过程中实际使用的流量差异,会导致费用有所变化,请以控制台显示的实际报价以及最终账单为准)。

      序号

      产品

      费用来源

      规格

      地域

      预估费用参考

      说明

      1

      应用型负载均衡ALB

      ALB实例费

      基础版

      华东2(上海)

      0.042元/时

      -

      2

      ALB容量费

      -

      0.042元/LCU

      -

      3

      云服务器ECS

      ECS1配置费

      实例:ecs.c7.large (按量付费,2 vCPU 4 GiB)

      系统盘:cloud_efficiency 40GiB

      华东2(上海)

      0.450元/时

      -

      4

      ECS2配置费

      0.450元/时

      -

      5

      消息服务MNS

      Queue占用费

      -

      华东2(上海)

      0.5元/日

      -

      6

      API请求次数费

      -

      2.0元/百万次

      -

      7

      对象存储OSS

      标准存储(本地冗余)容量(Storage)费

      -

      华东2(上海)

      0.12元/GB/月

      PUT类或GET类请求费

      -

      华东2(上海)

      0.01元/万次

      8

      函数计算FC

      函数调用次数费

      -

      华东2(上海)

      0.01元/万次

      -

      GPU使用量费

      -

      0.0007元/GB*秒

      -

      活跃vCPU使用量费

      -

      0.000127元/vCPU*秒

      -

      内存使用量费

      -

      0.0000127元/GB*秒

      -

      公网出流量费

      -

      0.50元/GB

      -

      9

      视频点播VOD

      媒资管理费

      -

      华东2(上海)

      0.12元/GB/月

      按量费用:6.55元/时

规划网络和资源

20

网络规划

请参考表格中的说明和方案默认示例值为每个规划项做详细规划并在实际部署时将默认示例值修改为您的实际规划。

规划项

数量

说明

地域

1

您的云服务部署的地域。选择地域的基本原则请参见地域和可用区

专有网络VPC

1

在部署过程中新建一个VPC作为本方案的专有网络。

交换机

2

本方案需要至少2台交换机,用来连接2台ECS实例。

安全组

1

用于限制专有网络VPC下云服务器ECS的网络流入和流出规则。

负载均衡ALB

1

本方案需要1台应用型负载均衡ALB实例,用于对网站的多台云服务器进行流量分发。它可以通过流量分发扩展应用系统的服务能力,通过消除单点故障提升应用系统的可用性。

规划云资源

请参考表格中的说明和方案默认示例值为每个规划项做详细规划并在实际部署时将默认示例值修改为您的实际规划。

规划项

数量

说明

ECS

1

本方案需要1台ECS实例,用于部署视频网站服务。

VOD

1

本方案需要为VOD启用1个存储管理。

MNS

1

本方案需要1个MNS队列用于接收和发送回调消息。

FC

1

本方案需要1个FC应用用于处理上传的视频。

OSS

2

本方案需要2个OSS Bucket,用于存储上传的视频和处理后的视频。

RAM角色

2

本方案需要1台应用型负载均衡ALB实例,用于对网站的多台云服务器进行流量分发。它可以通过流量分发扩展应用系统的服务能力,通过消除单点故障提升应用系统的可用性。

部署资源

60

规划好资源后,请按照以下步骤部署方案中的所有资源。

1.创建OSS

接下来您需要创建2个对象存储OSS Bucket,用于存储上传的视频文件和处理后的视频文件。

  1. 登录OSS管理控制台

  2. 在左侧导航栏,选择Bucket列表

  3. Bucket列表页面,单击创建Bucket

  4. 创建Bucket面板,配置以下参数,其他参数保留默认值,然后单击确定

    项目

    说明

    示例值

    Bucket名称

    Bucket 命名规范:

    • 命名长度为3~63个字符。

    • 只允许小写字母、数字、短横线(-),且不能以短横线开头或结尾。

    • Bucket名称在OSS范围内必须全局唯一。

    • vod-bucket-src

    • vod-bucket-target

    地域属性

    本方案以华东2(上海)为例。

    华东2(上海)

    存储类型

    视频数据会经常被访问,因此需要确保高可靠、高可用、高性能。

    标准存储

    读写权限

    对上传的视频的所有访问操作需要进行身份验证。

    私有。

2.创建MNS

您需要创建消息服务MNS队列用于接收视频点播服务推送的消息,并将其发送给函数计算FC。

  1. 登录消息服务MNS控制台

  2. 在左侧导航栏,单击队列列表

  3. 在顶部菜单栏,选择华东2(上海)地域。

  4. 队列列表页面,单击创建队列

  5. 创建队列面板,配置以下参数,其他参数保留默认值,然后单击确定

      项目

      说明

      示例值

      名称

      必须以英文字母或者数字开头,剩余名称可以是英文、数字、短划线(-)。

      mns-queue

3.创建VOD

使用创建的OSS Bucket作为视频点播服务的存储,然后使用MNS队列配置视频上传完成的回调。

  1. 登录视频点播管理控制台

  2. 启用存储管理。

    1. 在左侧导航栏,选择配置管理 > 媒资管理配置 > 存储管理

    2. 存储管理页面,单击添加OSS自有Bucket

    3. 添加OSS自有Bucket对话框,选择之前创建的Bucket的域名vod-bucket-src.oss-cn-shanghai.aliyuncs.com,然后单击确定

    4. 在添加的Bucket的右侧操作列,单击设为默认

  3. 配置MNS回调。

    1. 在左侧导航栏,选择配置管理 > 媒体处理配置 > 回调设置

    2. 回调设置页面,单击修改设置

    3. 回调设置对话框,配置以下参数,其他参数保留默认值,然后单击确定

      项目

      说明

      示例值

      回调方式

      本方案以MNS队列回调为例。

      MNS队列

      区域

      本方案以华东2(上海)为例。

      华东2(上海)

      队列

      选择之前创建的队列。

      mns-queue

      回调事件

      本方案以视频上传完成事件为例。

      视频上传完成

4.创建FC

接下来您需要创建1个FC应用,用于接收MNS推送的消息,并触发对应的函数对上传的视频进行处理并将其上传到另一个OSS Bucket。

  1. 登录函数计算控制台

  2. 创建应用。

    1. 在左侧导航栏,选择应用

    2. 应用页面,选择通过模板创建应用,搜索FFmpeg音视频处理集锦,选中后单击立即创建

    3. 创建应用页面,配置以下参数,其他参数保留默认值,然后单击创建并部署默认环境

      项目

      说明

      示例值

      部署类型

      本方案以直接部署为例。该方式代码将直接部署上线。后期更新维护项目需要对函数等资源进行操作,CI/CD等能力需要您手动适配。生产环境,建议您选择通过代码仓库部署。

      直接部署

      应用名称

      必须以字母开头,可含数字、字母(大小写敏感)、连字符,长度小于64个字符。

      fc-app

      地域

      本方案以之前规划的上海地域为例。

      华东2(上海)

      服务名

      应用所属的函数计算服务名称。

      fc-service

  3. 创建服务。

    1. 在左侧导航栏,选择服务及函数

    2. 服务列表页面,单击服务fc-service

    3. 函数管理页面,单击函数VideoWatermark

    4. 触发器管理页签下,单击创建触发器

    5. 函数VideoWatermark中创建触发器面板,配置以下参数,其他参数保留默认值,然后单击确定

      项目

      说明

      示例值

      触发器类型

      本方案以通过消息服务MNS队列触发器为例。

      消息服务MNS queue触发同步/异步调用

      名称

      只能包含字母、数字、下划线和中划线。不能以数字、中划线开头。长度在1-128之间。

      fc-trigger

      队列名称

      选择之前创建的队列。

      mns-queue

      调用方式

      本方案以异步调用为例。

      异步调用

  4. 配置函数。

    1. 触发器进入已启用状态后,选择函数代码页签。

    2. 函数代码页签下的index.py文件的内容,替换为以下代码示例,在替换代码示例时,将bucket_src替换为启用视频点播服务时配置的Bucket的名称,将bucket_target替换为存储处理后的视频使用的Bucket的名称。

      示例代码

      # -*- coding: utf-8 -*-
      import subprocess
      import oss2
      import logging
      import json
      import os
      import time
      import base64
      
      logging.getLogger("oss2.api").setLevel(logging.ERROR)
      logging.getLogger("oss2.auth").setLevel(logging.ERROR)
      
      LOGGER = logging.getLogger()
      
      '''
      1. function and bucket locate in same region
      2. service's role has OSSFullAccess
      3. event format
      {
          "bucket_name" : "test-bucket",
          "object_key" : "a.mp4",
          "output_dir" : "output/",
          "vf_args" : "drawtext=fontfile=/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc:text='hello函数计算':x=100:y=50:fontsize=24:fontcolor=red:shadowy=2",
          "filter_complex_args": "overlay=0:0:1"
      }
      
      filter_complex_args 优先级 > vf_args
      
      vf_args:
      - 文字水印
      vf_args = "drawtext=fontfile=/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc:text='hello函数计算':x=50:y=50:fontsize=24:fontcolor=red:shadowy=1"
      - 图片水印, 静态图片
      vf_args = "movie=/code/logo.png[watermark];[in][watermark]overlay=10:10[out]"
      
      filter_complex_args: 图片水印, 动态图片gif
      filter_complex_args = "overlay=0:0:1"
      '''
      
      # a decorator for print the excute time of a function
      
      
      def print_excute_time(func):
          def wrapper(*args, **kwargs):
              local_time = time.time()
              ret = func(*args, **kwargs)
              LOGGER.info('current Function [%s] excute time is %.2f seconds' %
                          (func.__name__, time.time() - local_time))
              return ret
          return wrapper
      
      
      def get_fileNameExt(filename):
          (fileDir, tempfilename) = os.path.split(filename)
          (shortname, extension) = os.path.splitext(tempfilename)
          return fileDir, shortname, extension
      
      
      @print_excute_time
      def handler(event, context):
          # 解析消息获取上传视频地址
          evt = json.loads(event)
          message = evt[0]["messageBody"]
          parsed_message = message.encode("utf-8").decode("unicode_escape")
          info_bytes = base64.urlsafe_b64decode(parsed_message)
          infoData = json.loads(info_bytes)
          fileUrl = infoData["FileUrl"]
          oss_bucket_name = "bucket_src"
      
          # 从上传视频地址fileUrl解析object key,fileUrl 如 bucketname.oss-cn-shanghai.aliyuncs.com/object-key.mp4
          url_split_array = fileUrl.split('com/', 1)
          object_key = url_split_array[1]
      
          output_dir = "output/"
          vf_args = "movie=/code/logo.png[watermark];[in][watermark]overlay=10:10[out]"
          filter_complex_args = "overlay=0:0:1"
      
          LOGGER.info('object_key:{}'.format(object_key))
      
          if not (vf_args or filter_complex_args):
              assert "at least one of 'vf_args' and 'filter_complex_args' has value"
      
          # 初始化oss client
          creds = context.credentials
          auth = oss2.StsAuth(creds.accessKeyId,
                              creds.accessKeySecret, creds.securityToken)
          oss_client = oss2.Bucket(
              auth, 'oss-%s-internal.aliyuncs.com' % context.region, oss_bucket_name)
      
          exist = oss_client.object_exists(object_key)
          LOGGER.info('exist:{}'.format(exist))
          if not exist:
              raise Exception("object {} is not exist".format(object_key))
      
          # 生成包含签名的url地址,允许ffmpeg命令临时访问视频
          input_path = oss_client.sign_url('GET', object_key, 3600)
      
          # 生成输出文件路径
          fileDir, shortname, extension = get_fileNameExt(object_key)
          dst_video_path = os.path.join("/tmp", "watermark_" + shortname + extension)
      
          # 构造添加水印命令并执行
          cmd = ["ffmpeg", "-y", "-i", input_path,
                 "-vf", vf_args, dst_video_path]
      
          if filter_complex_args:  # gif
              cmd = ["ffmpeg", "-y", "-i", input_path, "-ignore_loop", "0",
                     "-i", "/code/logo.gif", "-filter_complex", filter_complex_args, dst_video_path]
      
          LOGGER.info("cmd = {}".format(" ".join(cmd)))
          try:
              subprocess.run(
                  cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
          except subprocess.CalledProcessError as exc:
              LOGGER.error('returncode:{}'.format(exc.returncode))
              LOGGER.error('cmd:{}'.format(exc.cmd))
              LOGGER.error('output:{}'.format(exc.output))
              LOGGER.error('stderr:{}'.format(exc.stderr))
              LOGGER.error('stdout:{}'.format(exc.stdout))
      
          video_key = os.path.join(output_dir, fileDir, shortname + extension)
      
          # 初始化目标oss client,并上传带水印视频
          oss_client2 = oss2.Bucket(
              auth, 'oss-%s-internal.aliyuncs.com' % context.region, "bucket_target")
          oss_client2.put_object_from_file(video_key, dst_video_path)
      
          LOGGER.info("Uploaded {} to {} ".format(dst_video_path, video_key))
      
          # 移除本地文件
          os.remove(dst_video_path)
      
          return "ok"
    3. 单击部署代码

5.创建VPC和交换机

用于视频上传服务的云服务器ECS需要部署在专有网络VPC中并使用交换机通信因此,您需要创建1个专有网络和2个交换机。

  1. 登录专有网络管理控制台

  2. 在顶部菜单栏,选择华东2(上海)地域。

  3. 在左侧导航栏,单击专有网络

  4. 专有网络页面,单击创建专有网络

  5. 创建专有网络页面,配置1个专有网络和2台交换机。配置交换机时,请确保交换机所属的可用区的ECS是可用状态。

    项目

    说明

    示例值

    VPC名称

    建议您在部署过程中新建一个VPC作为本方案的专有网络。部署过程中填写VPC名称即可创建对应名称的VPC。

    长度为2~128个字符,以英文大小字母或中文开头,可包含数字、下划线(_)和连字符(-)。

    VPC_SH

    IPv4网段

    在创建VPC时,您必须按照无类域间路由块(CIDR block)的格式为您的专有网络划分私网网段。阿里云VPC支持的网段信息请参见专有网络组成部分

    在网络规划时可以按照管理网段-开发网段-测试网段-生产网段等规则做好规划。网段一旦投入使用,调整过程复杂,因此规划十分重要。

    192.168.0.0/16

    Vswitch名称

    建议您在部署过程中在新建的VPC内创建虚拟交换机。部署过程中填写交换机名称即可创建对应名称的虚拟交换机。

    长度为2~128个字符,以英文大小字母或中文开头,可包含数字、下划线(_)和连字符(-)。

    • vsw_001

    • vsw_002

    可用区

    在规划的地域内选择2个可用区,2台虚拟交换机分别部署在2个可用区。

    建议选择排序靠后的,一般此类可用区较新。新可用区资源更充沛,新规格也会在新的可用区优先上线。

    • 可用区 E

    • 可用区 F

    IPv4网段

    每台虚拟交换机需要一个IPv4网段

    • vsw_001:192.168.1.0/24

    • vsw_002:192.168.2.0/24

6.创建安全组

您已经在1个专有网络VPC下的2个可用区分别创建1台交换机。接下来您需要创建1个安全组,用于限制该专有网络VPC下的云服务器ECS网络流入和流出。

  1. 登录ECS管理控制台

  2. 在顶部菜单栏,选择华东2(上海)地域。

  3. 在左侧导航栏,选择网络与安全 > 安全组

  4. 安全组页面,单击创建安全组

  5. 创建安全组页面,创建1个安全组。

    项目

    说明

    示例值

    名称

    设置安全组的名称。

    SecurityGroup_1

    网络

    选择之前规划的专有网络VPC。

    VPC_SH

    安全组类型

    本方案需从公网拉取博客网站服务镜像,因此选择普通安全组,以实现公网出方向所有地址可访问。实际部署时,您建议选择安全性更高的企业级安全组。

    普通安全组

    入方向

    入方向除默认的端口号外,本方案还需添加8000端口号。

    8000

7.创建RAM角色

创建2个RAM角色,一个RAM角色用于云服务ECS获取STS临时访问凭证,另一个RAM角色用于视频上传服务获取STS临时访问凭证并上传视频到VOD。

  1. 登录RAM控制台

  2. 为云服务ECS创建RAM角色。

    1. 在左侧导航栏,选择身份管理 > 角色

    2. 角色页面,单击创建角色

    3. 创建角色面板的选择类型页签下,选择可信实体类型为阿里云服务,然后单击下一步

    4. 创建角色面板的配置角色页签下,配置以下参数,其他参数保留默认值,然后单击完成

      项目

      说明

      示例值

      角色类型

      本方案需自定义RAM角色,因此选择普通服务角色。

      普通服务角色

      角色名称

      允许英文字母、数字或 “-”。字符数应小于等于64个。

      EcsRamRoleTest

      选择受信服务

      本RAM角色角色由云服务器ECS扮演,因此选择云服务器。

      云服务器

    5. 创建角色面板的创建完成页签下,单击为角色授权

    6. 添加权限面板的系统策略页签下,搜索并选中AliyunSTSAssumeRoleAccess,然后单击确定

  3. 为视频上传服务创建RAM角色。

    1. 在左侧导航栏,选择身份管理 > 角色

    2. 角色页面,单击创建角色

    3. 创建角色面板的选择类型页签下,选择可信实体类型为阿里云账号,然后单击下一步

    4. 创建角色面板的配置角色页签下,配置以下参数,其他参数保留默认值,然后单击完成

      项目

      说明

      示例值

      角色名称

      允许英文字母、数字或“-”。字符数应小于等于64个。

      VodUploadRoleTest

      选择信任的云账号

      扮演本RAM角色的RAM角色所属云账号为当前云账号,因此选择当前云账号。

      当前云账号

    5. 创建角色面板的创建完成页签下,单击为角色授权

    6. 添加权限面板的系统策略页签下,搜索并选中AliyunSTSAssumeRoleAccessAliyunVODUploadAuth,然后单击确定

    7. 单击复制,保存角色的ARN。

      vodrole.png

8.创建ECS

您已经创建1个专有网络VPC。接下来您需要在2个可用区分别创建1台云服务器ECS,来部署视频上传服务。

  1. 登录ECS管理控制台

  2. 在顶部菜单栏,选择华东2(上海)地域。

  3. 在左侧导航栏,选择实例与镜像>实例

  4. 实例页面,单击创建实例

  5. 在云服务器ECS购买页面,创建2台云服务器ECS。如果当前可用区没有该实例规格,您可以选择其他实例规格。

    项目

    说明

    示例值

    实例名称

    2台实例分别需要一个实例名称。

    APP001

    APP002

    可用区

    本方案要求一台云服务器ECS实例与一个虚拟交换机位于同一可用区,另一台云服务器ECS实例与另一虚拟交换机位同一可用区。

    可用区 E

    可用区 F

    支付方式

    ECS实例的计费方式。

    ECS计费的详细信息请参见ECS计费方式概述

    按量付费

    实例规格

    ECS的实例规格及内核、vCPU数量。关于ECS选型的最佳实践请参见ECS选型最佳实践

    ecs.c7.large 2 vCPU 4 GiB

    镜像

    ECS的“装机盘”,为ECS实例提供操作系统、预装软件等。

    CentOS

    镜像版本

    镜像的版本。

    CentOS 7.9 64位

    系统盘类型

    硬盘类型。

    ESSD云盘

    系统盘容量

    硬盘容量。

    40 GiB

    公网IP

    用于队外服务

    分配公网 IPv4 地址

    带宽计费方式

    为节省流量成本,本方案以按使用流量为例。

    按使用流量

    带宽值

    本方案以5 Mbps为例。

    5 Mbps

    安全组

    使用之前创建的安全组。

    SecurityGroup_1

  6. 找到创建的ECS实例,选择图标.png > 实例设置 > 授予/收回RAM角色

  7. 在弹窗中,选择创建的实例RAM角色EcsRamRoleTest,单击确定完成授予。

9.创建ALB

接下来您需要创建1个公网类型的应用型负载均衡ALB并配置服务器组和监听,从而实现这个专有网络VPC下的2台云服务器ECS对外的公网访问和流量分发。

  1. 登录应用型负载均衡ALB控制台

  2. 创建应用型负载均衡ALB实例:

    1. 在顶部菜单栏左上角,选择华东2(上海)地域。

    2. 实例页面,单击创建应用型负载均衡

    3. 应用型负载均衡(按量付费)页面,购买1个ALB实例。

    4. 项目

      说明

      示例值

      实例网络类型

      本方案面向公网提供应用型负载均衡服务,公网可访问。

      公网

      VPC

      选择之前规划的VPC。

      VPC_SH

      可用区和交换机

      选择之前规划的交换机。

      • 上海可用区 E vsw_001

      • 上海可用区 F vsw_002

      IP模式

      每个可用区至少有一个IP,随着业务请求的增加,应用型负载均衡会自动扩展IP数量,此模式下应用型负载均衡具备超强弹性能力。

      动态

      协议版本

      本方案以IPV4为例。

      IPV4

      功能版本(实例费)

      本方案以基础版为例。

      基础版

      实例名称

      设置应用型负载均衡ALB实例的名称。

      ALB_SH

  3. 创建服务器组:

    1. 在左侧导航栏,选择应用型负载均衡ALB>服务器组

    2. 服务器组页面,单击创建服务器组

    3. 创建服务器组面板,设置服务器组名称,选择ECS所在的VPC,选择默认资源组,其他保持默认设置,然后单击创建

  4. 配置服务器组端口为8000:

    1. 服务器组页面,找到创建的服务器组实例,在其右侧操作列,单击编辑后端服务器

    2. 后端服务器组页签下,单击添加后端服务器

    3. 添加后端服务器面板,添加后端服务器组:

      1. 选中之前创建的ECS实例,单击下一步

      2. 再此选中之前创建的ECS实例,设置端口为8000,其他保持默认设置,然后单击确定

  5. 创建8000端口监听:

    1. 在左侧导航栏,选择应用型负载均衡ALB>实例

    2. 实例页面,找到创建的应用型负载均衡实例,在其右侧操作列,单击创建监听

    3. 配置监听页签下,设置监听端口为8000,单击下一步

    4. 选择服务器页签下,选择创建的服务器组,单击下一步

    5. 配置审核页签下,确认配置,然后单击提交

配置视频上传服务

30

创建云服务后,接下来您需要在2台云服务器ECS上分别执行以下操作配置视频上传服务。

  1. 登录ECS管理控制台

  2. 在顶部菜单栏,选择华东2(上海)地域。

  3. 在左侧导航栏,选择实例与镜像>实例

  4. 实例页面,找到创建的ECS实例,在其右侧操作列,单击远程连接

  5. 远程连接对话框的通过Workbench远程连接区域,单击立即登录,然后根据页面提示登录。

  6. 将以下命令中的<ECS_RAM_ROLE>替换为EcsRamRoleTest<ROLE_ARN>替换为VodUploadRoleTest的ARN,然后在root目录下执行以下命令配置视频上传服务。

    wget https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20230830/qhwb/server.zip
    yum install unzip -y
    unzip server.zip
    cd server
    pip3 install --upgrade pip
    pip3 install -r requirements.txt
    pip3 install uwsgi==2.0.22
    sed -i "s/socket=127.0.0.1:5000/http=0.0.0.0:8000/g" uwsgi.ini
    export ECS_RAM_ROLE=<ECS_RAM_ROLE>
    export ROLE_ARN=<ROLE_ARN>
    uwsgi uwsgi.ini

验证及清理

30

方案验证

部署云服务后,您可以测试上传视频文件并获取添加水印的视频文件来验证。

  1. 上传视频文件。

    1. 登录应用型负载均衡ALB控制台

    2. 实例页面的DNS名称,复制应用型负载均衡ALB实例的DNS地址,在浏览器访问上传视频页面地址DNS名称:8000

      2023-08-24_11-28-08.png

    3. 在上传视频页面,选择上海地域,上传一个视频。

  2. 获取添加水印的视频文件。

    1. 登录OSS管理控制台

    2. 在顶部菜单栏,选择华东2(上海)地域。

    3. 在左侧导航栏,选择Bucket列表

    4. Bucket列表页面,单击vod-bucket-target。

    5. 文件列表页面,找到添加水印的视频。

清理资源

在本方案中,您创建了2台云服务器ECS、1个ALB实例、2台交换机、1个专有网络VPC、2个OSS Bucket、1个MNS队列、1个FC应用、启用1个VOD服务。测试完方案后,您可以参考以下规则处理对应产品的实例,避免继续产生费用:

  1. 释放2台云服务器ECS实例:

    登录ECS控制台,在实例页面,找到目标实例,在操作列,选择216更多-竖向..png>释放设置,根据界面提示释放实例。

  2. 释放1个应用型负载均衡ALB实例:

    登录应用型负载均衡控制台实例页面,找到目标ALB实例,然后在操作列选择216更多-竖向..png>释放,按照界面提示释放实例。

  3. 释放1台交换机:

    登录专有网络控制台,在交换机页面,找到目标交换机,在操作列,单击删除,按照界面提示释放实例。

  4. 释放1个专有网络VPC:

    登录专有网络控制台,在专有网络页面,找到目标VPC,在操作列,单击删除,按照界面提示释放实例。

  5. 删除对象存储OSS Bucket。

    登录OSS管理控制台,在左侧导航栏,选择Bucket列表,单击目标Bucket,在文件列表,选择目标文件,然后单击彻底删除。在左侧导航栏,选择删除Bucket,单击删除Bucket,根据页面提示删除Bucket。

  6. 删除MNS队列。

    登录消息服务MNS控制台,在顶部菜单栏,选择华东2(上海)地域,在左侧导航栏,选择队列列表,在目标队列操作列,选择更多 > 删除,根据页面提示删除队列。

  7. 删除FC应用。

    登录函数计算控制台,在左侧导航栏,选择应用,在应用页面,找到目标应用,在其右侧操作列,单击删除,根据页面提示删除应用。

  8. 删除VOD服务。

    登录视频点播管理控制台,在左侧导航栏,选择媒资库>音/视频,删除目标文件。在左侧导航栏,选择配置管理 > 媒资管理配置 > 存储管理,在目标Bucket右侧操作列,单击删除,根据页面提示删除Bucket。

一键部署

40

https://www.aliyun.com/solution/tech-solution/vsaps

方案概览

视频存储与处理是指基于阿里云服务提供高可靠存储和实时自动化服务,能够满足用户对视频存储、转码、截图、播放、直播等功能的需求。本技术解决方案以搭建一个视频存储和处理服务为例,为您演示:

  • 如何搭建一个视频存储和处理服务。

  • 观察添加水印后的视频。

方案架构

方案提供的默认设置完成部署后在阿里云上搭建的网站运行环境如下图所示。实际部署时您可以根据资源规划修改部分设置,但最终形成的运行环境与下图相似。

1.jpeg

本方案的技术架构包括以下基础设施和云服务:

  • 2个云服务器ECS:部署上传和下载视频网站服务。

  • 1个负载均衡ALB:对外提供访问并将用户请求分配到不同云服务器ECS上的博客网站服务。

  • 1个专有网络VPC:为应用型负载均衡ALB、云服务器ECS等云资源形成云上私有网络。

  • 2台交换机:将2台云服务器ECS连接在同一网络上,实现它们之间的通信,并提供基本的网络分段和隔离功能。

  • 视频点播VOD:将客户端上传视频的消息推送到MNS。

  • 消息服务MNS:接收VOD推送的消息并将其发送给FC。

  • 函数计算FC:收到客户端上传视频的消息后,调用函数从Bucket中获取视频并处理,然后将其上传到另一个Bucket。

  • 对象存储OSS:1个Bucket作为视频点播服务的存储服务,用于存储客户端上传的视频,另1个Bucket用于存储处理后的视频。

  • 2个RAM角色:1个RAM角色用于云服务ECS获取STS临时访问凭证,另一个RAM角色用于视频上传服务获取STS临时访问凭证并上传视频到VOD。

部署准备

10

开始部署前,请按以下指引完成账号申请、账号充值、RAM用户创建和授权。

准备账号

  1. 如果您还没有阿里云账号,请访问阿里云账号注册页面,根据页面提示完成注册。阿里云账号是您使用云资源的付费实体,因此是部署方案的必要前提。

  2. 开通以下云服务:MNSOSSVODFCEventBridge

    说明
    • 因为本方案中的FC Trigger依赖EventBridge,所以您还需要开通EventBridge。

    • 如果点开MNS链接提示开通报错,说明已经开通,您可以直接登录MNS控制台进行确认。

  3. 完成一键授权:AliyunVODDefaultRoleAliyunFCServerlessDevsRole

  4. 为阿里云账号充值

    1. 为节省成本,本方案默认全部选择使用按量付费资源,使用按量付费资源需要确保账户余额不小于100元。

    2. 完成本方案的部署及体验,预计产生费用不超过5元(假设您选择最低规格资源,且资源运行时间不超过30分钟。实际情况中可能部分实例无法购买需要根据实际情况调整资源规格,同时因您操作过程中实际使用的流量差异,会导致费用有所变化,请以控制台显示的实际报价以及最终账单为准)。

      序号

      产品

      费用来源

      规格

      地域

      预估费用参考

      说明

      1

      应用型负载均衡ALB

      ALB实例费

      基础版

      华东2(上海)

      0.042元/时

      -

      2

      ALB容量费

      -

      0.042元/LCU

      -

      3

      云服务器ECS

      ECS1配置费

      实例:ecs.c7.large (按量付费,2 vCPU 4 GiB)

      系统盘:cloud_efficiency 40GiB

      华东2(上海)

      0.450元/时

      -

      4

      ECS2配置费

      0.450元/时

      -

      5

      消息服务MNS

      Queue占用费

      -

      华东2(上海)

      0.5元/日

      -

      6

      API请求次数费

      -

      2.0元/百万次

      -

      7

      对象存储OSS

      标准存储(本地冗余)容量(Storage)费

      -

      华东2(上海)

      0.12元/GB/月

      PUT类或GET类请求费

      -

      华东2(上海)

      0.01元/万次

      8

      函数计算FC

      函数调用次数费

      -

      华东2(上海)

      0.01元/万次

      -

      GPU使用量费

      -

      0.0007元/GB*秒

      -

      活跃vCPU使用量费

      -

      0.000127元/vCPU*秒

      -

      内存使用量费

      -

      0.0000127元/GB*秒

      -

      公网出流量费

      -

      0.50元/GB

      -

      9

      视频点播VOD

      媒资管理费

      -

      华东2(上海)

      0.12元/GB/月

      按量费用:6.55元/时

一键部署

15

一键部署基于阿里云资源编排服务ROS(Resource Orchestration Service)实现,ROS模板已定义好脚本,可自动化地完成云资源的创建和配置,提高资源的创建和部署效率。ROS模板完成的内容包括:

操作步骤

您可以通过下方提供的ROS一键部署链接,来自动化地完成这些资源的创建和配置:

  • 创建2个云服务器ECS。

  • 创建1个负载均衡ALB。

  • 创建1个专有网络VPC。

  • 创建2台交换机。

  • 创建1个视频点播VOD。

  • 创建1个消息服务MNS队列。

  • 创建1个函数计算FC服务。

  • 创建2个对象存储OSS Bucket。

  • 创建2个RAM角色。

  1. 一键部署资源。

    1. 单击一键部署,并选择华东2(上海)地域。

      重要

      为避免因地域不支持云服务而导致部署失败,建议您参考本方案选择进行部署测试。实际部署生产时,请确保您选择的地域已支持以上云服务。

    2. 配置模板参数页面修改资源栈名称,配置ECS实例、OSS Bucket。填写完所有必选信息并确认后单击创建开始一键配置。

    3. 资源栈信息页面的状态显示为创建成功时表示一键配置完成。

  2. 部署函数计算代码。

    1. 在资源栈页面选择事件页签,找到FcTrigger,在其右侧单击资源ID。

    2. 函数 VideoWatermark 详情页面,选择函数代码页签。

    3. 函数代码页签下的index.py文件的内容,替换为以下代码示例,在替换代码示例时,将bucket_src替换为启用视频点播服务时配置的Bucket的名称,将bucket_target替换为存储处理后的视频使用的Bucket的名称。

      示例代码

      # -*- coding: utf-8 -*-
      import subprocess
      import oss2
      import logging
      import json
      import os
      import time
      import base64
      
      logging.getLogger("oss2.api").setLevel(logging.ERROR)
      logging.getLogger("oss2.auth").setLevel(logging.ERROR)
      
      LOGGER = logging.getLogger()
      
      '''
      1. function and bucket locate in same region
      2. service's role has OSSFullAccess
      3. event format
      {
          "bucket_name" : "test-bucket",
          "object_key" : "a.mp4",
          "output_dir" : "output/",
          "vf_args" : "drawtext=fontfile=/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc:text='hello函数计算':x=100:y=50:fontsize=24:fontcolor=red:shadowy=2",
          "filter_complex_args": "overlay=0:0:1"
      }
      
      filter_complex_args 优先级 > vf_args
      
      vf_args:
      - 文字水印
      vf_args = "drawtext=fontfile=/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc:text='hello函数计算':x=50:y=50:fontsize=24:fontcolor=red:shadowy=1"
      - 图片水印, 静态图片
      vf_args = "movie=/code/logo.png[watermark];[in][watermark]overlay=10:10[out]"
      
      filter_complex_args: 图片水印, 动态图片gif
      filter_complex_args = "overlay=0:0:1"
      '''
      
      # a decorator for print the excute time of a function
      
      
      def print_excute_time(func):
          def wrapper(*args, **kwargs):
              local_time = time.time()
              ret = func(*args, **kwargs)
              LOGGER.info('current Function [%s] excute time is %.2f seconds' %
                          (func.__name__, time.time() - local_time))
              return ret
          return wrapper
      
      
      def get_fileNameExt(filename):
          (fileDir, tempfilename) = os.path.split(filename)
          (shortname, extension) = os.path.splitext(tempfilename)
          return fileDir, shortname, extension
      
      
      @print_excute_time
      def handler(event, context):
          # 解析消息获取上传视频地址
          evt = json.loads(event)
          message = evt[0]["messageBody"]
          parsed_message = message.encode("utf-8").decode("unicode_escape")
          info_bytes = base64.urlsafe_b64decode(parsed_message)
          infoData = json.loads(info_bytes)
          fileUrl = infoData["FileUrl"]
          oss_bucket_name = "bucket_src"
      
          # 从上传视频地址fileUrl解析object key,fileUrl 如 bucketname.oss-cn-shanghai.aliyuncs.com/object-key.mp4
          url_split_array = fileUrl.split('com/', 1)
          object_key = url_split_array[1]
      
          output_dir = "output/"
          vf_args = "movie=/code/logo.png[watermark];[in][watermark]overlay=10:10[out]"
          filter_complex_args = "overlay=0:0:1"
      
          LOGGER.info('object_key:{}'.format(object_key))
      
          if not (vf_args or filter_complex_args):
              assert "at least one of 'vf_args' and 'filter_complex_args' has value"
      
          # 初始化oss client
          creds = context.credentials
          auth = oss2.StsAuth(creds.accessKeyId,
                              creds.accessKeySecret, creds.securityToken)
          oss_client = oss2.Bucket(
              auth, 'oss-%s-internal.aliyuncs.com' % context.region, oss_bucket_name)
      
          exist = oss_client.object_exists(object_key)
          LOGGER.info('exist:{}'.format(exist))
          if not exist:
              raise Exception("object {} is not exist".format(object_key))
      
          # 生成包含签名的url地址,允许ffmpeg命令临时访问视频
          input_path = oss_client.sign_url('GET', object_key, 3600)
      
          # 生成输出文件路径
          fileDir, shortname, extension = get_fileNameExt(object_key)
          dst_video_path = os.path.join("/tmp", "watermark_" + shortname + extension)
      
          # 构造添加水印命令并执行
          cmd = ["ffmpeg", "-y", "-i", input_path,
                 "-vf", vf_args, dst_video_path]
      
          if filter_complex_args:  # gif
              cmd = ["ffmpeg", "-y", "-i", input_path, "-ignore_loop", "0",
                     "-i", "/code/logo.gif", "-filter_complex", filter_complex_args, dst_video_path]
      
          LOGGER.info("cmd = {}".format(" ".join(cmd)))
          try:
              subprocess.run(
                  cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
          except subprocess.CalledProcessError as exc:
              LOGGER.error('returncode:{}'.format(exc.returncode))
              LOGGER.error('cmd:{}'.format(exc.cmd))
              LOGGER.error('output:{}'.format(exc.output))
              LOGGER.error('stderr:{}'.format(exc.stderr))
              LOGGER.error('stdout:{}'.format(exc.stdout))
      
          video_key = os.path.join(output_dir, fileDir, shortname + extension)
      
          # 初始化目标oss client,并上传带水印视频
          oss_client2 = oss2.Bucket(
              auth, 'oss-%s-internal.aliyuncs.com' % context.region, "bucket_target")
          oss_client2.put_object_from_file(video_key, dst_video_path)
      
          LOGGER.info("Uploaded {} to {} ".format(dst_video_path, video_key))
      
          # 移除本地文件
          os.remove(dst_video_path)
      
          return "ok"
    4. 单击部署代码

验证及清理

15

方案验证

部署云服务后,您可以测试上传视频文件并获取添加水印的视频文件来验证。

  1. 上传视频文件。

    1. 登录应用型负载均衡ALB控制台

    2. 实例页面的DNS名称,复制应用型负载均衡ALB实例的DNS地址,在浏览器访问上传视频页面地址DNS名称:8000

      2023-08-24_11-28-08.png

    3. 在上传视频页面,选择上海地域,上传一个视频。

  2. 获取添加水印的视频文件。

    1. 登录OSS管理控制台

    2. 在顶部菜单栏,选择华东2(上海)地域。

    3. 在左侧导航栏,选择Bucket列表

    4. Bucket列表页面,单击vod-bucket-target。

    5. 文件列表页面,找到添加水印的视频。

清理资源

在本方案中,您创建了2台云服务器ECS实例、1个应用型负载均衡ALB实例、2个交换机、1个专有网络VPC、1个云数据库PolarDB MySQL版实例。测试完方案后,您可以参考以下规则处理对应产品的实例,避免继续产生费用:

  1. 手动删除对象存储OSS Bucket。

    登录OSS管理控制台,在左侧导航栏,选择Bucket列表,单击目标Bucket,在文件列表,选择目标文件,然后单击彻底删除。在左侧导航栏,选择删除Bucket,单击删除Bucket,根据页面提示删除Bucket。

  2. 手动删除FC服务。

    登录函数计算控制台,在左侧导航栏,选择服务及函数,在服务列表页面,找到目标服务,在其右侧操作列,单击删除,根据页面提示删除服务。

  3. 手动删除VOD服务。

    登录视频点播管理控制台,在左侧导航栏,选择媒资库>音/视频,删除目标文件。在左侧导航栏,选择配置管理 > 媒资管理配置 > 存储管理,在目标Bucket右侧操作列,单击删除,根据页面提示删除Bucket。

  4. 一键自动删除其他资源。

    1. 登录ROS控制台

    2. 在左侧导航栏,选择资源栈

    3. 资源栈页面的顶部选择部署的资源栈所在地域,找到资源栈,然后在其右侧操作列,单击删除

    4. 删除资源栈对话框,选择删除方式释放资源,然后单击确定,根据提示完成资源释放。