aws ffmpeg+ lambda来完成视频stream的截图 python docker 版
Posted spcof
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了aws ffmpeg+ lambda来完成视频stream的截图 python docker 版相关的知识,希望对你有一定的参考价值。
大纲
FFmpeg被广泛应用于音/视频流处理领域。对于简单的需求,我们可以直接运行FFmpeg二进制程序命令就可以完成。但是对于定制性的功能,则需要熟悉系统的代码设计框架,进行二次开发。文本讨论的是在AWS无服务架构的Lambda上,如何通过Docker部署FFmpeg二进制程序。
1 确定Lambda运行时环境
Lambda运行时决定了其运行的CPU架构、操作系统和辅助软件。不同语言的运行时环境不同,相同语言的不同版本的运行时不同,所以这步的确认非常重要,否则会造成FFmpeg与Lambda不兼容的问题。下面是从AWS官方摘录了运行时信息,仅供参考。
1.1 Lambda系统、镜像、内核版本
系统 | 镜像 | Linux 内核 |
---|---|---|
Amazon Linux | 镜像 – amzn-ami-hvm-2018.03.0.20181129-x86_64-gp2 | 4.14 |
Amazon Linux 2 | 自定义 | 4.14 |
1.2 运行时
1.2.1 Python
Python 运行时 | 标识符 | AWS Python的软件工具包 | 操作系统 | 架构 |
---|---|---|---|---|
Python 3.9 | python3.9 | boto3-1.20.32 botocore-1.23.32 | Amazon Linux 2 | x86_64,arm64 |
Python 3.8 | python3.8 | boto3-1.20.32 botocore-1.23.32 | Amazon Linux 2 | x86_64,arm64 |
Python 3.7 | python3.7 | boto3-1.20.32 botocore-1.23.32 | Amazon Linux | x86_64 |
Python 3.6 | python3.6 | boto3-1.20.32 botocore-1.23.32 | Amazon Linux | x86_64 |
1.2.2 Java
Java 运行时 | 标识符 | JDK | 作系统 | 架构 |
---|---|---|---|---|
Java 11 | java11 | amazon-corretto-11 | Amazon Linux 2 | x86_64,arm64 |
Java 8 | java8.al2 | amazon-corretto-11 | Amazon Linux 2 | x86_64,arm64 |
Java 8 | java8 | amazon-corretto-11 | Amazon Linux | x86_64 |
本例使用Python3.9版本,其操作系统是Amazon Linux 2,Linux内核是“4.14”,架构是“x86_64,arm64”。在这两种CPU架构中,我们选择适用面更广的x86_64。如果选择arm64,后续FFmpeg选择,以及Lambda函数运行时也要做出相应调整。
2 启动EC2
在EC2的控制面板中启动最低配置(t2.micro)的实例,同时AMI选择和Lambda一致的Linux内核版本。CPU架构,我们选择常见的X86_64。这些配置也决定了后续我们下载使用的FFmpeg的版本。
可以创建一对新的密钥对,也可以使用老的密钥对。因为我们使用浏览器连接EC2,所以这个环节不重要。
由于Docker需要一定磁盘,我们需要给该虚拟机20G的磁盘空间。
待实例处于running状态,可以使用浏览器连接它。
3 编写调用FFmpeg的代码
由于通过Docker部署的Lambda在Web端看不到代码,也不能在Web端提交代码,于是只能在Docker中提前把代码部署好。
在/home/ec2-user下使用vim新建一个文件lambda_handle.py,并填充内容
import subprocess
import shlex
def lambda_handler(event, context):
if not event:
return
'statusCode': 400,
'body': json.dumps('event error')
ffmpeg_cmd = "/usr/bin/ffmpeg -version"
command = shlex.split(ffmpeg_cmd)
p = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return
'statusCode': 200,
'body': str(p.stdout, encoding='utf-8')
这儿我们约定FFmpeg的路径是/usr/bin/ffmpeg,这将在Docker文件中确保该路径正确。
4 生成docker镜像
4.1 安装和启动Docker服务
sudo yum install -y docker
sudo service docker start
4.2 编写Dockerfile脚本
在/home/ec2-user目录下使用vim新建Dockerfile脚本文件,并填入以下内容。其中倒数第三步,是将FFmpeg放到之前约定的/usr/bin目录下;倒数第二步,是将上步编写的Python脚本放到指定目录;最后一步是设置Lambda函数入口。
FROM public.ecr.aws/lambda/python:3.9
RUN export ENVIRONMENT=$ENVIRONMENT:online
RUN /var/lang/bin/python3.9 -m pip install --upgrade pip
RUN yum -y install gcc libjpeg-devel zlib-devel gcc-c++ python3-wheel epel-release wget tar gzip xz
RUN wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz
RUN wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz.md5
RUN md5sum -c ffmpeg-release-amd64-static.tar.xz.md5
RUN tar -xvf ffmpeg-release-amd64-static.tar.xz
RUN mv ffmpeg-5.0.1-amd64-static/ffmpeg /usr/bin
COPY ./lambda_handle.py ./
CMD ["lambda_handle.lambda_handler"]
4.3 生成镜像
sudo docker build -t lambda_ffmpeg:latest -f Dockerfile .
5 推送镜像
5.1 创建存储库
在AWS Elastic Container Registry中创建一个名为lambda_ffmpeg的存储库。
5.2 给EC2赋予角色
5.2.1 创建策略
选择Elastic Container Registry服务,并限制资源为上述创建的ECR库。为了方便测试,暂时先赋予全部权限。(生产环境中要严格遵从最小权限原则。)
最后创建了名为“ElasticContainerRegistryLmbdaFfmpegFullAccess”的策略。
5.2.2 创建角色
在IAM中创建一个名为ffmpeg_ecr_builder的角色。
给这个角色暂时赋予上步创建的策略。
5.2.3 给EC2绑定角色
5.3 修改docker用户
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker
5.4 推送镜像
执行1、3和4指令。我们就可以在ECR中看到相应镜像。
6 部署Lambda
创建一个名为ffmpeg_from_ecr,从容器映像中选择映像的Lambda。
运行一次测试,可以看到部署成功了。
参考文献
作者
Jie Wu
尝试使用 ffmpeg 时 AWS Lambda 权限被拒绝
【中文标题】尝试使用 ffmpeg 时 AWS Lambda 权限被拒绝【英文标题】:AWS Lambda permission denied when trying to use ffmpeg 【发布时间】:2016-07-03 23:16:44 【问题描述】:我想编写一个响应 S3 put 事件的处理程序,以转换任何上传到 mp4 的 avi 文件。我在 Java、Eclipse 中使用 AWS 工具包插件进行操作。对于视频转换,我使用带有ffmpeg-cli-wrapper 的ffmpeg,并且我在源代码树中提供了ffmpeg 的静态(linux)二进制文件。
我发现当我上传函数时,二进制文件被放入/var/task
,但是当我尝试使用我编写的测试函数时,我得到一个“权限被拒绝”的错误。
import net.bramp.ffmpeg.FFmpeg;
public class LambdaFunctionHandler implements RequestHandler<S3Event, String>
private static final String FFMPEG = "/var/task/ffmpeg";
public String handleRequest(S3Event event, Context context)
try
FFmpeg ff = new FFmpeg(FFMPEG);
System.out.println(ff.version());
catch (Exception e)
e.printStackTrace();
return "foo";
堆栈跟踪的第一行:java.io.IOException: Cannot run program "/var/task/ffmpeg": error=13, Permission denied
。
如何执行这个二进制文件?我已经按照其他人的建议和chmod 755
在上传之前完成了二进制文件,但没有任何区别。
【问题讨论】:
【参考方案1】:AWS Lambda 在 Amazon Linux 上运行。这是一个已知问题。尝试构建(启用静态)并检查它是否适用于 Amazon Linux 并上传该二进制文件。您没有chmod
/var/task/
中文件的权限。或者试试这个可行的解决方案:
ffmpeg
移动到/tmp
chmod 755 /tmp/ffmpeg
致电/tmp/ffmpeg
请参阅此discussion 了解更多信息。
【讨论】:
如何移动文件?是我可以从命令行执行一次还是需要在方法开始时在代码中执行此操作? 在方法的开始处。如果mv
失败,请尝试cp
。它总是对我有用。
很抱歉没有早点回复您。我用ProcessBuilder
照你说的做,一切都很好。感谢您的帮助!
你也可以在 Java 中使用 Files.copy【参考方案2】:
我最近遇到了这个问题,在弄乱了各种手动解决方案之后,真正解决了这个问题的是:
-
创建一个 Lambda 层,在
bin/
文件夹中仅包含 ffmpeg
二进制文件
创建一个 Lambda 函数来实现该层,并在 python 代码中运行/opt/bin/ffmpeg
见https://aws.amazon.com/blogs/media/processing-user-generated-content-using-aws-lambda-and-ffmpeg/
【讨论】:
【参考方案3】:正如 helloV 所提到的,您可能必须包含一个静态 ffmpeg 二进制文件并将其复制到某个位置并从那里执行。 详细解答,(node.js代码)给here
【讨论】:
以上是关于aws ffmpeg+ lambda来完成视频stream的截图 python docker 版的主要内容,如果未能解决你的问题,请参考以下文章
Lambda 上的 FFmpeg 转码导致无法使用(静态)音频
使用 aws lambda node js 获取存储在 s3 存储桶中的视频的视频元数据