如何使用aws 的serverless 的lambda 来实现ffmpeg的截图
## 描述:
业务需求在aws云上面实现直播,随机截取直播流进行截图,上传到S3桶里面去。
业务其实很简单,难点是在如何在serverless的lambda来部署ffmpeg,因为lambda的无状态特性,所以我们无法直接在lambda上安装ffmpeg的安装包。
这就让我们在aws的lambda上部署ffmpeg变的困难起来,但是方法总比困难多,我有两个解决方案:
1. 通过docker 部署到aws 的lambda
2. 通过自定义层的方法部署到lambda
今天这里我只讲第二种方法,因为第二种方法及其的简单高效,还可以看到自己写的代码,比docker友好很多,本篇文章分两段前面一段是用来介绍如何用lambda搭建ffmpeg,后面一段是用来用来介绍ffmpeg如果截取视频流。
通过自定义层的方式来部署ffmpeg到lambda
准备事项:
- 准备一台与lambda系统相同的ec2(临时使用用完就可以delete掉了)
- 创建一个lambda用的layer
- 创建一个lambda
1.准备一台与lambda系统相同的ec2
上图是与lambda版本相同的linux系统
这台ec2是用来下载ffmpeg,解压重新压缩ffmpeg,是为lambda准备ffmpeg层的,这些任务结束后这个ec2就可以删除掉了
上命令:
这4条命令是用来下载ffmpeg和使用md5来检查文件和解压ffmpeg安装包
wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz
wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz.md5
md5sum -c ffmpeg-release-amd64-static.tar.xz.md5
tar xvf ffmpeg-release-amd64-static.tar.xz
FFmpeg 二进制文件位于文件夹“ffmpeg-4.3.1-amd64-static”中
为 Lambda 层创建一个 ZIP 包,如下所示:
mkdir -p ffmpeg/bin
cp ffmpeg-4.3.1-amd64-static/ffmpeg ffmpeg/bin/
cd ffmpeg
zip -r ../ffmpeg.zip .
好!我们可以通过WinSCP讲ffmpeg.zip下载到本地或通过aws cli 上传到指定的s3中
2.创建lambda的layer
填写完名称和描述,上传我们压缩好的ffmpeg.zip文件,选择兼容运行的version,层的许可证避免被函
好那么我们的最重要的一点层就创建出来了。
3.创建一个lambda函数
创建一个lambda函数来运行我们和ffmpeg相关的代码
1). 创建一个lambda函数
2.绑定我们在第一步创建的lambda layer
3. build我们的代码到指定的lambda函数上面
好!到此我们的lambda部署ffmpeg的步骤就全部说完了,我们接下来介绍一下我们是如何实现截取直播流截图的
通过lambda + ffmpeg 来实现视频流截图
我们的直播途径是aws ivs(Amazon Interactive Video Service),不的不说这是一个非常快的来实现直播的一种方案,当我们开始直播的时候
ivs会给我们一个m3u8的直播连接。这时候我们可以通ffmpeg来读取直播stream,获取stream里面的指定/随机的一帧进行截图。
下面是一个简单直播的架构图:
在这里插入图片描述接下来我就简单的介绍一下这个简单的架构图
cloudfront: CND 全球边缘站点用于缓存直播图片等信息
api gateway: 他可以使我们通过internet 对lambda中的api 进行访问
vpc: 我们的所有服务都在aws的vpc下进行部署
video_lambda: 直播api 应用层lambda 用于调用ivs负责 用户登录注册,ivs开播、下播,数据的存储
ffmpeg_lambda: 开播后负责对直播stream进行截图
factor_lambda: 对图片进行动态的分辨率的改变
今天我们讲的就是inplay_ffmpeg这个lambda,这个lambda的视频流url是通过lambda的event来传递给该lambda的,该lambda获取到event中的url
会通过ffmpeg对视频流进行截图,下面我们介绍一下ffmpeg命令
/opt/bin/ffmpeg -probesize 32768 -i {pull_stream_url} -y -t 0.001 -ss 1 -f image2 -r 1 -
/opt/bin/ffmpeg :是ffmpeg的执行开头,为什么要加opt/bin呢,是因为在lambda中我们的执行package在 /opt/bin文件夹下面的
-probesize 32768:以字节为单位设置探测大小,即分析获取流信息的数据大小
-i: 输入
-y: 无需询问即可覆盖输出文件
-t: 当用作输入选项(之前-i)时,限制从输入文件读取数据 的持续时间。我这里设置的是0.001秒
-ss:开始时间。
-f:强制输入或输出文件格式。
image2: 图像文件解复用器。
-r: 提取图像的频率
-: 输出
以上命令的意思是当ffmpeg获取到m3u8的视频stream链接的时候通过我设定的开始时间和截取频率对stream进行截图并按照指定的格式进行输出,最后获取到stream上传到s3桶里面。
code 如下:文章来源:https://www.toymoban.com/news/detail-832344.html
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0 (https://spdx.org/licenses/MIT-0.html)
import json
import os
import subprocess
import shlex
import boto3
import time
S3_DESTINATION_BUCKET = "inplay-video-image"
def lambda_handler(event, context):
if not event:
print("event is null")
return False
time.sleep(30)
s3_client = boto3.client('s3')
file_name = "{file_path}/covers.jpeg".format(file_path = event.get('user_id'))
ffmpeg_cmd = "/opt/bin/ffmpeg -probesize 32768 -i {pull_stream_url} -y -t 0.001 -ss 1 -f image2 -r 1 -".format(pull_stream_url = event.get("pull_stream_url"))
print(ffmpeg_cmd)
command1 = shlex.split(ffmpeg_cmd)
p1 = subprocess.run(command1, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(p1.stdout)
resp = s3_client.put_object(Body=p1.stdout, Bucket=S3_DESTINATION_BUCKET, Key=file_name)
return {
'statusCode': 200,
'body': json.dumps('Processing complete successfully')
}
这种方案并不是唯一的解决方案,所以并不是绝对正确的,这个文章主要讲如何用lambda + ffmpeg 快速部署一个具有ffmpeg层的lambda 来实现serverless的一种方法。文章来源地址https://www.toymoban.com/news/detail-832344.html
到了这里,关于aws ffmpeg+ lambda来完成视频stream的截图 python 版的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!