第 12 章 · AWS 实战参考
搭一个完整的 VOD 平台
本章你会看到:AWS 上搭一个 VOD 平台的完整服务清单、架构图、关键 API 调用、其他云的等价服务、真实的成本量级。
预计阅读时间:20 分钟
12.1AWS 媒体服务家族
AWS 把 VOD/直播相关服务叫 AWS Elemental。核心四件套:
| 服务 |
干什么 |
| AWS Elemental MediaConvert | 文件转码(离线、VOD) |
| AWS Elemental MediaLive | 实时编码(直播) |
| AWS Elemental MediaPackage | 流媒体打包(HLS/DASH/CMAF)、DRM |
| AWS Elemental MediaStore / MediaTailor | 低延迟 origin / 广告插入 |
配合基础服务
| 服务 |
干什么 |
| Amazon S3 | 存储 |
| Amazon CloudFront | CDN |
| AWS Lambda | 触发器、轻量处理 |
| AWS Step Functions | 工作流编排 |
| Amazon DynamoDB | 资产元数据存储 |
| Amazon SNS/SQS | 事件通知、异步队列 |
| Amazon CloudWatch | 监控告警 |
12.2官方参考架构
AWS 官方的 Video on Demand on AWS 方案架构:
┌──────────────┐ ┌──────────────┐
│ 用户 │ │ Creator │
│ 观看 │ │ (Uploader) │
└──────────────┘ └──────────────┘
▲ │
│ ⑥ HTTPS │ ① PutObject
│ ▼
┌──────────────┐ ┌──────────────┐
│ CloudFront │ │ S3 Source │
│ (CDN) │ │ Bucket │
└──────────────┘ └──────────────┘
▲ │
│ ⑤ origin fetch │ ② EventBridge
│ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ MediaPackage │◄──│ S3 │◄─────────────────────│ Step │
│ -VOD │ │ Destination │ │ Functions │
│ (packaging) │ │ Bucket │ └──────────────┘
└──────────────┘ └──────────────┘ │
│ ▲ │
│ SPEKE │ ▼
▼ │ ┌──────────────┐
┌──────────────┐ └─────────────────────│ MediaConvert │
│ DRM License │ │ (Transcode) │
│ Server │ └──────────────┘
│ (EZDRM等) │ │
└──────────────┘ ▼
┌──────────────┐
│ Lambda │
│ (post-proc, │
│ notify) │
└──────────────┘
流程
1. Creator 上传文件到 S3 Source Bucket
2. S3 Event → Step Functions 被触发
3. Lambda 先 probe + 验证
4. Step Functions 调用 MediaConvert 转码
5. 转码结果写到 S3 Destination Bucket
6. MediaPackage-VOD 打包 HLS/DASH + DRM
7. CloudFront 作为 CDN 分发
8. 完成后 Lambda 通知用户
12.3一步步走一遍
步骤 1:准备 S3 Bucket
# Source bucket (上传原片)
aws s3 mb s3://my-vod-source --region us-east-1
# Destination bucket (转码产物)
aws s3 mb s3://my-vod-dest --region us-east-1
# 启用 EventBridge 通知
aws s3api put-bucket-notification-configuration \
--bucket my-vod-source \
--notification-configuration '{
"EventBridgeConfiguration": {}
}'
步骤 2:创建 IAM Role 给 MediaConvert 用
MediaConvert 需要从 S3 读、往 S3 写:
aws iam create-role --role-name MediaConvertRole \
--assume-role-policy-document file://trust-policy.json
aws iam attach-role-policy --role-name MediaConvertRole \
--policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess
步骤 3:MediaConvert Job 模板(最小可用)
{
"Role": "arn:aws:iam::123456789012:role/MediaConvertRole",
"Settings": {
"Inputs": [{
"FileInput": "s3://my-vod-source/episode01.mov",
"AudioSelectors": {
"Audio Selector 1": {"DefaultSelection": "DEFAULT"}
}
}],
"OutputGroups": [{
"Name": "CMAF",
"OutputGroupSettings": {
"Type": "CMAF_GROUP_SETTINGS",
"CmafGroupSettings": {
"Destination": "s3://my-vod-dest/ep01/",
"SegmentLength": 4,
"FragmentLength": 2,
"WriteHlsManifest": "ENABLED",
"WriteDashManifest": "ENABLED"
}
},
"Outputs": [
{
"NameModifier": "_1080p",
"VideoDescription": {
"Width": 1920, "Height": 1080,
"CodecSettings": {
"Codec": "H_264",
"H264Settings": {
"RateControlMode": "QVBR",
"QvbrSettings": {"QvbrQualityLevel": 8},
"MaxBitrate": 5000000,
"GopSize": 2,
"GopSizeUnits": "SECONDS"
}
}
},
"AudioDescriptions": [{
"CodecSettings": {
"Codec": "AAC",
"AacSettings": {
"Bitrate": 128000,
"SampleRate": 48000,
"CodingMode": "CODING_MODE_2_0"
}
}
}]
},
{ "NameModifier": "_720p", /* ... 2500 kbps ... */ },
{ "NameModifier": "_540p", /* ... 1200 kbps ... */ },
{ "NameModifier": "_360p", /* ... 600 kbps ... */ }
]
}]
}
}
关键参数:
| 参数 |
值 |
说明 |
| QvbrQualityLevel | 8 | QVBR 目标质量(1-10,越高越好) |
| MaxBitrate | 5,000,000 | 峰值限制 |
| GopSize | 2 SECONDS | 2 秒一个 GOP |
| SegmentLength | 4 | 4 秒切片 |
| FragmentLength | 2 | 2 秒 fragment(子切片,for CMAF) |
提交 Job:
aws mediaconvert create-job --cli-input-json file://job.json \
--endpoint-url https://abc.mediaconvert.us-east-1.amazonaws.com
步骤 4:加 DRM (SPEKE)
在 CMAF OutputGroup 里加:
"Encryption": {
"EncryptionMethod": "SAMPLE_AES",
"SpekeKeyProvider": {
"ResourceId": "episode01",
"SystemIds": [
"edef8ba9-79d6-4ace-a3c8-27dcd51d21ed", // Widevine
"94ce86fb-07ff-4f43-adb8-93d2fa968ca2", // FairPlay
"9a04f079-9840-4286-ab92-e65be0885f95" // PlayReady
],
"Url": "https://speke.ezdrm.com/v2",
"CertificateArn": "arn:aws:acm:..."
}
}
SPEKE URL 指向 DRM 厂商(EZDRM/PallyCon等)的 endpoint。
步骤 5:CloudFront 分发
创建一个 distribution 指向 S3 Destination Bucket:
aws cloudfront create-distribution --distribution-config file://cf-config.json
关键配置:
• Origin: S3 Destination Bucket
• Viewer Protocol Policy: Redirect HTTP to HTTPS
• Allowed Methods: GET, HEAD
• Cache Policy: Managed-CachingOptimizedForUncompressedObjects
• Origin Access Control: 启用,防止绕过 CloudFront 直接访问 S3
• Signed URLs: 需要时启用 Trusted Key Groups
步骤 6:Signed URL 生成
客户端请求播放时后端生成短时效签名 URL:
# Python 示例
from datetime import datetime, timedelta
import boto3
cf_signer = boto3.client('cloudfront-signer', ...)
def generate_signed_url(video_path, user_id, expires_in=3600):
url = f"https://d1234.cloudfront.net/{video_path}"
expires = datetime.utcnow() + timedelta(seconds=expires_in)
# 用 CloudFront key-pair 签名
signed = cf_signer.generate_presigned_url(url, date_less_than=expires)
return signed
步骤 7:Step Functions 编排
状态机串起整个流程(见第 11 章 §11.11 编排工具)。
12.4Terraform 一键部署片段
用 Terraform 声明基础设施:
# Source bucket
resource "aws_s3_bucket" "source" {
bucket = "my-vod-source"
}
# Destination bucket
resource "aws_s3_bucket" "dest" {
bucket = "my-vod-dest"
}
# EventBridge rule to trigger Step Functions on S3 upload
resource "aws_cloudwatch_event_rule" "upload" {
name = "vod-upload-trigger"
event_pattern = jsonencode({
source = ["aws.s3"]
"detail-type" = ["Object Created"]
detail = {
bucket = { name = [aws_s3_bucket.source.bucket] }
}
})
}
# Step Functions state machine
resource "aws_sfn_state_machine" "vod_pipeline" {
name = "vod-pipeline"
role_arn = aws_iam_role.sfn_role.arn
definition = file("${path.module}/vod_pipeline.asl.json")
}
resource "aws_cloudwatch_event_target" "sfn" {
rule = aws_cloudwatch_event_rule.upload.name
arn = aws_sfn_state_machine.vod_pipeline.arn
role_arn = aws_iam_role.event_bridge_role.arn
}
# CloudFront distribution
resource "aws_cloudfront_distribution" "vod" {
origin {
domain_name = aws_s3_bucket.dest.bucket_regional_domain_name
origin_id = "s3-vod-dest"
s3_origin_config {
origin_access_identity = aws_cloudfront_origin_access_identity.vod.cloudfront_access_identity_path
}
}
enabled = true
default_root_object = ""
default_cache_behavior {
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "s3-vod-dest"
viewer_protocol_policy = "redirect-to-https"
cache_policy_id = data.aws_cloudfront_cache_policy.caching_optimized.id
trusted_key_groups = [aws_cloudfront_key_group.vod.id]
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
viewer_certificate {
cloudfront_default_certificate = true
}
}
12.5成本估算
MediaConvert 转码成本
按"输出分钟数 x 编码复杂度"计费:
| 档位 |
单价(美东 us-east-1) |
| Basic SD (< 30 fps, < 720p, AVC) | $0.0075 / output min |
| Basic HD (< 30 fps, 720p-1080p, AVC) | $0.015 / output min |
| Pro HD (60 fps 或 HEVC 或 HDR) | $0.030 / output min |
| Pro UHD (4K+) | $0.060 / output min |
| AV1 加价 | 约 2-3x |
💰 一部 90 分钟电影 x 6 档 (4 H.264 + 2 H.265)
90 min x 4 档 x $0.015 = $5.4 (H.264)
90 min x 2 档 x $0.030 = $5.4 (H.265)
总转码成本 ≈ $10.8 / 电影
S3 存储
• 存储 Standard:$0.023 / GB / 月(us-east-1)
• 一部电影所有版本 ~ 3 GB → $0.07 / 月
• 大库(10 万小时):约 1 PB → $23,000 / 月
• 冷内容用 S3 Glacier 可省 80%
CloudFront 出站带宽
按区域 $0.005–$0.08 / GB,阶梯折扣。
MediaPackage JIT packaging
约 $0.065 / GB(源文件流量)。大量访问热门内容划算。
12.6其他云的等价服务
| AWS |
阿里云 |
腾讯云 |
Google Cloud |
Azure |
| S3 | OSS | COS | GCS | Blob Storage |
| MediaConvert | VOD / IMM | VOD / MPS | Transcoder API | Media Services |
| MediaPackage | VOD DRM | VOD DRM | Media CDN | Media Services DRM |
| CloudFront | CDN / DCDN | CDN / ECDN | Cloud CDN / Media CDN | Azure CDN |
| Step Functions | Serverless Workflow | SCF + WorkflowRun | Workflows | Durable Functions |
| Lambda | FC / SAE | SCF | Cloud Functions | Azure Functions |
选云建议:
• 全球业务、海外为主:AWS(覆盖最广)
• 中国大陆为主:阿里云 / 腾讯云
• 短剧出海:AWS + 阿里云国际 / 火山引擎(多云分发)
12.7一个典型短剧 APP 的 AWS 账单(推断)
按 DAU 2M、日均 30 分钟观看、720p 主码流推断:
| 科目 |
月成本量级 |
| S3 存储 (10 PB) | $50K-$150K |
| MediaConvert (每天 100 集新上) | $1K-$5K |
| CloudFront (24 PB/月) | $400K-$800K |
| MediaPackage JIT | $50K-$150K |
| Lambda + Step Functions | $5K-$20K |
| DynamoDB + RDS | $10K-$30K |
| DRM SaaS | $20K-$80K |
| 合计 | $500K-$1.2M |
CDN 带宽是绝对大头
降本三板斧:更好的编解码器、Per-Title 编码、多 CDN 竞价。
12.8从 0 到生产上线 Roadmap
第 1 周:最小可用 DEMO
• 开 AWS 账号,启用 S3、MediaConvert、CloudFront
• 手动跑一个 MediaConvert Job,转出一个 HLS
• 用 Safari 打开 m3u8 能播 ✅
第 2-4 周:自动化管线
• Step Functions 串联:S3 Upload → MediaConvert → S3 → CloudFront
• 后端生成 Signed URL
• iOS/Android APP 集成播放器
第 2-3 个月:生产特性
• 多档码率 + per-title 优化
• DRM 接入(EZDRM / PallyCon)
• QoE 数据接入 Mux 或自建
• 多 CDN 调度
第 4-6 个月:规模化
• H.265 / AV1 档位
• LL-HLS(如果做直播)
• 多区域部署 + 跨区复制
• 成本优化(Spot、Glacier 冷归档)
| 阶段 |
目标 |
| 第 1 周 | 手动跑一个 MediaConvert Job → Safari 播 m3u8 ✅ |
| 第 2-4 周 | Step Functions 自动化 + Signed URL + APP 集成播放器 |
| 第 2-3 月 | 多码率 + DRM + QoE 接入 + 多 CDN |
| 第 4-6 月 | H.265/AV1 + 多区域 + 成本优化(Spot/Glacier) |
12.9常见陷阱
❌ CloudFront 签名 URL 缓存命中率为 0
原因:签名参数(Signature, Expires, Key-Pair-Id)进入了 cache key。
解决:在 Cache Policy 里只把 path 作为 cache key,signed parameters 放 Query String 但不参与缓存。
❌ MediaConvert 输出文件异常大
原因:没配 QVBR 或 MaxBitrate,CRF 太低导致峰值爆炸。
解决:QvbrQualityLevel: 7-8 + MaxBitrate 约束。
❌ HLS 在 iOS 上卡在加载
原因:Master Playlist 里缺 CODECS 属性。
解决:确保每个 EXT-X-STREAM-INF 都带 CODECS="avc1.xxxxxx,mp4a.40.2"。
❌ 跨境分发延迟高
原因:CloudFront 回源到 us-east-1 S3 对亚洲用户延迟高。
解决:启用 CloudFront Origin Shield,放在离 origin 近的地方;或者 S3 跨区复制,让 CloudFront 就近回源。
📌 本章要点回顾
1. AWS 核心四件套:MediaConvert + MediaPackage + CloudFront + S3。
2. Step Functions 做编排,Lambda 做轻处理。
3. 用 SPEKE 接 DRM 托管服务。
4. 生产环境用 Terraform 声明式管理。
5. 成本里 CDN 带宽是大头,其次是存储,转码相对便宜。
6. 其他云都有对等服务;选云按市场定位。
7. 从 MVP → 生产一般 2-6 个月。
🎉🎊🏆
恭喜读完全书!
你已经系统了解了 VOD 流媒体的完整技术栈 —— 从视频基础、编解码、容器封装、流媒体协议、DRM 加密、CDN 分发、播放器、QoE 监控、AI/ML 增强、端到端工作流,一直到 AWS 实战。
下一步建议:
• 按本章 12.8 的 Week 1 动手搭一个 DEMO
• 重读 ReelShort 案例分析
• 查阅术语速查表
© 2026 Zmead · VOD 流媒体技术全解