方案概览
部署准备
一键部署
验证及清理
手动部署
150
https://www.aliyun.com/solution/tech-solution/vsaps
方案概览
视频存储与处理是指基于阿里云服务提供高可靠存储和实时自动化服务,能够满足用户对视频存储、转码、截图、播放、直播等功能的需求。本技术解决方案以搭建一个视频存储和处理服务为例,为您演示:
如何搭建一个视频存储和处理服务。
观察添加水印后的视频。
方案架构
方案提供的默认设置完成部署后在阿里云上搭建的网站运行环境如下图所示。实际部署时您可以根据资源规划修改部分设置,但最终形成的运行环境与下图相似。
本方案的技术架构包括以下基础设施和云服务:
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用户创建和授权。
准备账号
如果您还没有阿里云账号,请访问阿里云账号注册页面,根据页面提示完成注册。阿里云账号是您使用云资源的付费实体,因此是部署方案的必要前提。
开通以下云服务:轻量消息队列(原MNS)、OSS、VOD、FC、EventBridge。
说明因为本方案中的FC Trigger依赖EventBridge,所以您还需要开通EventBridge。
如果点开MNS链接提示开通报错,说明已经开通,您可以直接登录轻量消息队列(原MNS)控制台进行确认。
为节省成本,本方案默认全部选择使用按量付费资源,使用按量付费资源需要确保账户余额不小于100元。
完成本方案的部署及体验,预计产生费用不超过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
规划好资源后,请按照以下步骤部署方案中的所有资源。
接下来您需要创建2个对象存储OSS Bucket,用于存储上传的视频文件和处理后的视频文件。
登录OSS管理控制台。
在左侧导航栏,选择Bucket列表。
在Bucket列表页面,单击创建Bucket。
在创建Bucket面板,配置以下参数,其他参数保留默认值,然后单击确定。
命名长度为3~63个字符。
只允许小写字母、数字、短横线(
-
),且不能以短横线开头或结尾。Bucket名称在OSS范围内必须全局唯一。
vod-bucket-src
vod-bucket-target
项目 | 说明 | 示例值 |
Bucket名称 | Bucket 命名规范: | |
地域属性 | 本方案以华东2(上海)为例。 | 华东2(上海) |
存储类型 | 视频数据会经常被访问,因此需要确保高可靠、高可用、高性能。 | 标准存储 |
读写权限 | 对上传的视频的所有访问操作需要进行身份验证。 | 私有。 |
您需要创建轻量消息队列用于接收视频点播服务推送的消息,并将其发送给函数计算FC。
在左侧导航栏,单击队列列表。
在顶部菜单栏,选择华东2(上海)地域。
在队列列表页面,单击创建队列。
在创建队列面板,配置以下参数,其他参数保留默认值,然后单击确定。
项目
说明
示例值
名称
必须以英文字母或者数字开头,剩余名称可以是英文、数字、短划线(-)。
mns-queue
使用创建的OSS Bucket作为视频点播服务的存储,然后使用轻量消息队列配置视频上传完成的回调。
登录视频点播管理控制台。
启用存储管理。
在左侧导航栏,选择配置管理 > 媒资管理配置 > 存储管理。
在存储管理页面,单击添加OSS自有Bucket。
在添加OSS自有Bucket对话框,选择之前创建的Bucket的域名
vod-bucket-src.oss-cn-shanghai.aliyuncs.com
,然后单击确定。在添加的Bucket的右侧操作列,单击设为默认。
配置MNS回调。
在左侧导航栏,选择配置管理 > 媒体处理配置 > 回调设置。
在回调设置页面,单击修改设置。
在回调设置对话框,配置以下参数,其他参数保留默认值,然后单击确定。
项目
说明
示例值
回调方式
本方案以轻量消息队列(原MNS)回调为例。
轻量消息队列(原MNS)
区域
本方案以华东2(上海)为例。
华东2(上海)
队列
选择之前创建的队列。
mns-queue
回调事件
本方案以视频上传完成事件为例。
视频上传完成
接下来您需要创建1个FC应用,用于接收轻量消息队列(原MNS)推送的消息,并触发对应的函数对上传的视频进行处理并将其上传到另一个OSS Bucket。
登录函数计算控制台。
说明本方案以函数计算 2.0控制台为例,若当前您的函数计算控制台右上角有返回函数计算 2.0字样,请单击返回2.0版本控制台。
创建应用。
在左侧导航栏,选择应用。
在应用页面,选择通过模板创建应用,搜索FFmpeg音视频处理集锦,选中后单击立即创建。
在创建应用页面,配置以下参数,其他参数保留默认值,然后单击创建并部署默认环境。
项目
说明
示例值
部署类型
本方案以直接部署为例。该方式代码将直接部署上线。后期更新维护项目需要对函数等资源进行操作,CI/CD等能力需要您手动适配。生产环境,建议您选择通过代码仓库部署。
直接部署
应用名称
必须以字母开头,可含数字、字母(大小写敏感)、连字符,长度小于64个字符。
fc-app
地域
本方案以之前规划的上海地域为例。
华东2(上海)
服务名
应用所属的函数计算服务名称。
fc-service
创建服务。
在左侧导航栏,选择服务及函数。
在服务列表页面,单击服务
fc-service
。在函数管理页面,单击函数
VideoWatermark
。在触发器管理页签下,单击创建触发器。
在函数VideoWatermark中创建触发器面板,配置以下参数,其他参数保留默认值,然后单击确定。
项目
说明
示例值
触发器类型
本方案以通过轻量消息队列(原MNS)触发器为例。
轻量消息队列(原MNS)queue触发同步/异步调用
名称
只能包含字母、数字、下划线和中划线。不能以数字、中划线开头。长度在1-128之间。
fc-trigger
队列名称
选择之前创建的队列。
mns-queue
调用方式
本方案以异步调用为例。
异步调用
配置函数。
触发器进入已启用状态后,选择函数代码页签。
在函数代码页签下的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"
单击部署代码。
用于视频上传服务的云服务器ECS需要部署在专有网络VPC中并使用交换机通信因此,您需要创建1个专有网络和2个交换机。
登录专有网络管理控制台。
在顶部菜单栏,选择华东2(上海)地域。
在左侧导航栏,单击专有网络。
在专有网络页面,单击创建专有网络。
在创建专有网络页面,配置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
您已经在1个专有网络VPC下的2个可用区分别创建1台交换机。接下来您需要创建1个安全组,用于限制该专有网络VPC下的云服务器ECS网络流入和流出。
登录ECS管理控制台。
在顶部菜单栏,选择华东2(上海)地域。
在左侧导航栏,选择网络与安全 > 安全组。
在安全组页面,单击创建安全组。
在创建安全组页面,创建1个安全组。
项目
说明
示例值
名称
设置安全组的名称。
SecurityGroup_1
网络
选择之前规划的专有网络VPC。
VPC_SH
安全组类型
本方案需从公网拉取博客网站服务镜像,因此选择普通安全组,以实现公网出方向所有地址可访问。实际部署时,您建议选择安全性更高的企业级安全组。
普通安全组
入方向
入方向除默认的端口号外,本方案还需添加8000端口号。
8000
创建2个RAM角色,一个RAM角色用于云服务ECS获取STS临时访问凭证,另一个RAM角色用于视频上传服务获取STS临时访问凭证并上传视频到VOD。
登录RAM控制台。
为云服务ECS创建RAM角色。
在左侧导航栏,选择身份管理 > 角色。
在角色页面,单击创建角色。
在创建角色面板的选择类型页签下,选择可信实体类型为阿里云服务,然后单击下一步。
在创建角色面板的配置角色页签下,配置以下参数,其他参数保留默认值,然后单击完成。
项目
说明
示例值
角色类型
本方案需自定义RAM角色,因此选择普通服务角色。
普通服务角色
角色名称
允许英文字母、数字或 “-”。字符数应小于等于64个。
EcsRamRoleTest
选择受信服务
本RAM角色由云服务器ECS扮演,因此选择云服务器。
云服务器
在创建角色面板的创建完成页签下,单击为角色授权。
在添加权限面板的系统策略页签下,搜索并选中
AliyunSTSAssumeRoleAccess
,然后单击确定。
为视频上传服务创建RAM角色。
在左侧导航栏,选择身份管理 > 角色。
在角色页面,单击创建角色。
在创建角色面板的选择类型页签下,选择可信实体类型为阿里云账号,然后单击下一步。
在创建角色面板的配置角色页签下,配置以下参数,其他参数保留默认值,然后单击完成。
项目
说明
示例值
角色名称
允许英文字母、数字或“-”。字符数应小于等于64个。
VodUploadRoleTest
选择信任的云账号
扮演本RAM角色的RAM角色所属云账号为当前云账号,因此选择当前云账号。
当前云账号
在创建角色面板的创建完成页签下,单击为角色授权。
在添加权限面板的系统策略页签下,搜索并选中
AliyunSTSAssumeRoleAccess
和AliyunVODUploadAuth
,然后单击确定。单击复制,保存角色的ARN。
您已经创建1个专有网络VPC。接下来您需要在2个可用区分别创建1台云服务器ECS,来部署视频上传服务。
登录ECS管理控制台。
在顶部菜单栏,选择华东2(上海)地域。
在左侧导航栏,选择实例与镜像>实例。
在实例页面,单击创建实例。
在云服务器ECS购买页面,创建2台云服务器ECS。如果当前可用区没有该实例规格,您可以选择其他实例规格。
项目
说明
示例值
实例名称
2台实例分别需要一个实例名称。
APP001
APP002
可用区
本方案要求一台云服务器ECS实例与一个虚拟交换机位于同一可用区,另一台云服务器ECS实例与另一虚拟交换机位同一可用区。
可用区 E
可用区 F
支付方式
ECS实例的计费方式。
ECS计费的详细信息请参见ECS计费方式概述。
按量付费
实例规格
ECS的实例规格及内核、vCPU数量。关于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
找到创建的ECS实例,选择 > 实例设置 > 授予/收回RAM角色。
在弹窗中,选择创建的实例RAM角色
EcsRamRoleTest
,单击确定完成授予。
接下来您需要创建1个公网类型的应用型负载均衡ALB并配置服务器组和监听,从而实现这个专有网络VPC下的2台云服务器ECS对外的公网访问和流量分发。
创建应用型负载均衡ALB实例:
在顶部菜单栏左上角,选择华东2(上海)地域。
在实例页面,单击创建应用型负载均衡。
在应用型负载均衡(按量付费)页面,购买1个ALB实例。
上海可用区 E vsw_001
上海可用区 F vsw_002
项目
说明
示例值
实例网络类型
本方案面向公网提供应用型负载均衡服务,公网可访问。
公网
VPC
选择之前规划的VPC。
VPC_SH
可用区和交换机
选择之前规划的交换机。
IP模式
每个可用区至少有一个IP,随着业务请求的增加,应用型负载均衡会自动扩展IP数量,此模式下应用型负载均衡具备超强弹性能力。
动态
协议版本
本方案以IPV4为例。
IPV4
功能版本(实例费)
本方案以基础版为例。
基础版
实例名称
设置应用型负载均衡ALB实例的名称。
ALB_SH
创建服务器组:
在左侧导航栏,选择应用型负载均衡ALB>服务器组。
在服务器组页面,单击创建服务器组。
在创建服务器组面板,设置服务器组名称,选择ECS所在的VPC,选择默认资源组,其他保持默认设置,然后单击创建。
配置服务器组端口为8000:
在服务器组页面,找到创建的服务器组实例,在其右侧操作列,单击编辑后端服务器。
在后端服务器组页签下,单击添加后端服务器。
在添加后端服务器面板,添加后端服务器组:
选中之前创建的ECS实例,单击下一步。
再此选中之前创建的ECS实例,设置端口为8000,其他保持默认设置,然后单击确定。
创建8000端口监听:
在左侧导航栏,选择应用型负载均衡ALB>实例。
在实例页面,找到创建的应用型负载均衡实例,在其右侧操作列,单击创建监听。
在配置监听页签下,设置监听端口为8000,单击下一步。
在选择服务器页签下,选择创建的服务器组,单击下一步。
在配置审核页签下,确认配置,然后单击提交。
配置视频上传服务
30
创建云服务后,接下来您需要在2台云服务器ECS上分别执行以下操作配置视频上传服务。
登录ECS管理控制台。
在左侧导航栏,选择实例与镜像>实例。
在顶部菜单栏,选择华东2(上海)地域。
在实例页面,找到创建的ECS实例,在其右侧操作列,单击远程连接。
在远程连接对话框的通过Workbench远程连接区域,单击立即登录,然后根据页面提示登录。
将以下命令中的
<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
方案验证
部署云服务后,可以通过测试上传视频文件并获取添加水印的视频文件来进行验证。
一、通过函数计算FC日志,监控任务执行
开启函数计算FC日志
登录函数计算控制台,在左侧导航栏选择服务及函数,在服务列表页面找到目标服务,点击服务名进入服务详情,然后点击VideoWatermark函数,找到调用日志标签,按照页面提示点击一键启用开启日志功能
上传视频文件
登录应用型负载均衡ALB控制台,在实例页面的DNS名称,复制应用型负载均衡ALB实例的DNS地址,在浏览器访问上传视频页面地址DNS名称:8000
。
在上传视频页面,选择上海地域,选择并上传视频文件。
查看转码任务进度
登录函数计算控制台,进入VideoWatermark函数详情页,点击调用日志 > 函数日志,确认函数计算是否成功调用并处理上传的视频文件。
当任务执行完毕,可以在请求列表中看到调用结果和执行时间。
监控轻量消息队列(原MNS)
登录轻量消息队列(原MNS)控制台,在队列列表中点击 video-website-mns-queue,在云监控中查看消息队列中的消息流转情况,确保视频上传消息已成功推送并被函数计算FC消费。
二、通过查看OSS中的文件,验证视频水印添加效果
清理资源
在本方案中,您创建了2台云服务器ECS、1个ALB实例、2台交换机、1个专有网络VPC、2个OSS Bucket、1个轻量消息队列(原MNS)、1个FC应用、启用1个VOD服务。测试完方案后,您可以参考以下规则处理对应产品的实例,避免继续产生费用:
释放2台云服务器ECS实例:
登录ECS控制台,在实例页面,找到目标实例,在操作列,选择>释放设置,根据界面提示释放实例。
释放1个应用型负载均衡ALB实例:
登录应用型负载均衡控制台,在实例页面,找到目标ALB实例,然后在操作列选择>释放,按照界面提示释放实例。
释放1台交换机:
登录专有网络控制台,在交换机页面,找到目标交换机,在操作列,单击删除,按照界面提示释放实例。
释放1个专有网络VPC:
登录专有网络控制台,在专有网络页面,找到目标VPC,在操作列,单击删除,按照界面提示释放实例。
删除对象存储OSS Bucket。
登录OSS管理控制台,在左侧导航栏,选择Bucket列表,单击目标Bucket,在文件列表,选择目标文件,然后单击彻底删除。在左侧导航栏,选择删除Bucket,单击删除Bucket,根据页面提示删除Bucket。
删除轻量消息队列(原MNS)
登录轻量消息队列(原MNS)控制台,在顶部菜单栏,选择华东2(上海)地域,在左侧导航栏,选择队列列表,在目标队列操作列,选择更多 > 删除,根据页面提示删除队列。
删除FC应用。
登录函数计算控制台,在左侧导航栏,选择应用,在应用页面,找到目标应用,在其右侧操作列,单击删除,根据页面提示删除应用。
删除VOD服务。
登录视频点播管理控制台,在左侧导航栏,选择媒资库>音/视频,删除目标文件。在左侧导航栏,选择配置管理 > 媒资管理配置 > 存储管理,在目标Bucket右侧操作列,单击删除,根据页面提示删除Bucket。
一键部署
40
https://www.aliyun.com/solution/tech-solution/vsaps
方案概览
视频存储与处理是指基于阿里云服务提供高可靠存储和实时自动化服务,能够满足用户对视频存储、转码、截图、播放、直播等功能的需求。本技术解决方案以搭建一个视频存储和处理服务为例,为您演示:
如何搭建一个视频存储和处理服务。
观察添加水印后的视频。
方案架构
方案提供的默认设置完成部署后在阿里云上搭建的网站运行环境如下图所示。实际部署时您可以根据资源规划修改部分设置,但最终形成的运行环境与下图相似。
本方案的技术架构包括以下基础设施和云服务:
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用户创建和授权。
准备账号
如果您还没有阿里云账号,请访问阿里云账号注册页面,根据页面提示完成注册。阿里云账号是您使用云资源的付费实体,因此是部署方案的必要前提。
开通以下云服务:轻量消息队列(原MNS)、OSS、VOD、FC、EventBridge
说明因为本方案中的FC Trigger依赖EventBridge,所以您还需要开通EventBridge。
如果点开MNS链接提示开通报错,说明已经开通,您可以直接登录轻量消息队列(原MNS)控制台进行确认。
为节省成本,本方案默认全部选择使用按量付费资源,使用按量付费资源需要确保账户余额不小于100元。
完成本方案的部署及体验,预计产生费用不超过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角色。
一键部署资源。
单击一键部署,并选择华东2(上海)地域。
重要为避免因地域不支持云服务而导致部署失败,建议您参考本方案选择进行部署测试。实际部署生产时,请确保您选择的地域已支持以上云服务。
在配置模板参数页面修改资源栈名称,配置ECS实例、OSS Bucket。填写完所有必选信息并确认后单击创建开始一键配置。
当资源栈信息页面的状态显示为创建成功时表示一键配置完成。
部署函数计算代码。
在资源栈页面选择事件页签,找到
FcTrigger
,在其右侧单击资源ID。在函数 VideoWatermark 详情页面,选择函数代码页签。
在函数代码页签下的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"
单击部署代码。
验证及清理
15
方案验证
部署云服务后,可以通过测试上传视频文件并获取添加水印的视频文件来进行验证。
一、通过函数计算FC日志,监控任务执行
开启函数计算FC日志
登录函数计算控制台,在左侧导航栏选择服务及函数,在服务列表页面找到目标服务,点击服务名进入服务详情,然后点击VideoWatermark函数,找到调用日志标签,按照页面提示点击一键启用开启日志功能
上传视频文件
登录应用型负载均衡ALB控制台,在实例页面的DNS名称,复制应用型负载均衡ALB实例的DNS地址,在浏览器访问上传视频页面地址DNS名称:8000
。
在上传视频页面,选择上海地域,选择并上传视频文件。
查看转码任务进度
登录函数计算控制台,进入VideoWatermark函数详情页,点击调用日志 > 函数日志,确认函数计算是否成功调用并处理上传的视频文件。
当任务执行完毕,可以在请求列表中看到调用结果和执行时间。
监控轻量消息队列(原MNS)
登录轻量消息队列(原MNS)控制台,在队列列表中点击 video-website-mns-queue,在云监控中查看消息队列中的消息流转情况,确保视频上传消息已成功推送并被函数计算FC消费。
二、通过查看OSS中的文件,验证视频水印添加效果
清理资源
在本方案中,您创建了2台云服务器ECS实例、1个应用型负载均衡ALB实例、2个交换机、1个专有网络VPC、1个云数据库PolarDB MySQL版实例。测试完方案后,您可以参考以下规则处理对应产品的实例,避免继续产生费用:
手动删除对象存储OSS Bucket。
登录OSS管理控制台,在左侧导航栏,选择Bucket列表,单击目标Bucket,在文件列表,选择目标文件,然后单击彻底删除。在左侧导航栏,选择删除Bucket,单击删除Bucket,根据页面提示删除Bucket。
手动删除FC服务。
登录函数计算控制台,在左侧导航栏,选择服务及函数,在服务列表页面,找到目标服务,在其右侧操作列,单击删除,根据页面提示删除服务。
手动删除VOD服务。
登录视频点播管理控制台,在左侧导航栏,选择媒资库>音/视频,删除目标文件。在左侧导航栏,选择配置管理 > 媒资管理配置 > 存储管理,在目标Bucket右侧操作列,单击删除,根据页面提示删除Bucket。
一键自动删除其他资源。
登录ROS控制台。
在左侧导航栏,选择资源栈。
在资源栈页面的顶部选择部署的资源栈所在地域,找到资源栈,然后在其右侧操作列,单击删除。
在删除资源栈对话框,选择删除方式为释放资源,然后单击确定,根据提示完成资源释放。
方案部署进度 25%