【AICon】 如何构建高效的 RAG 系统?RAG 技术在实际应用中遇到的挑战及应对策略?>>> 了解详情
写点什么

Serverless 实战:分分钟实现视频压缩与格式转换

  • 2020-06-10
  • 本文字数:7885 字

    阅读完需:约 26 分钟

Serverless实战:分分钟实现视频压缩与格式转换

在 Serverless 架构的应用实践中,有一个非常实在的应用:视频处理。


腾讯云的函数计算平台是这样描述视频处理场景的:


视频应用、社交应用等场景下,用户上传的图片、音视频的总量大、频率高,对处理系统的实时性和并发能力都有较高的要求。例如:对于用户上传的视频短片,我们可以使用多个云函数对其分别处理,对应不同的清晰度(1080p、720p 等),以满足不同场景下用户的需求,适应移动网络带宽较小且不稳定的特性。



在阿里云的函数计算也有相关的描述:



由此可见,视频的压缩/转码等操作是 Serverless 架构的一个典型"应用"。那么问题来看,如何在 Serverless 架构下实现视频压缩与转码?

准备开始 ffmpeg

什么是 ffmpeg?百度百科是这样描述的:


FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用 LGPL 或 GPL 许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库 libavcodec,为了保证高可移植性和编解码质量,libavcodec 里很多 code 都是从头开发的。

FFmpeg 在 Linux 平台下开发,但它同样也可以在其它操作系统环境中编译运行,包括 Windows、Mac OS X 等。这个项目最早由 Fabrice Bellard 发起,2004 年至 2015 年间由 Michael Niedermayer 主要负责维护。许多 FFmpeg 的开发人员都来自 MPlayer 项目,而且当前 FFmpeg 也是放在 MPlayer 项目组的服务器上。项目的名称来自 MPEG 视频编码标准,前面的"FF"代表"Fast Forward"。


在实际生产生活中,ffmpeg 也是一个非常好的工具,我们可以利用这个工具来进行图像的压缩/转码等操作。


在 ffmpeg 官网,我们可以看到有不同的操作系统、文件可供选择:



也就是说,我们如果要在云函数中使用这个模块,那么就要有这样一个模块是在云函数所在的环境下可以运行起来的,根据云函数的文档可以看到:



我们要有一个在 CentOS 操作系统下可以使用的 ffmpeg,接下来,我们就准备这个文件:


  1. 在 CentOS 操作系统上,下载源码包:wget http://www.ffmpeg.org/releases/ffmpeg-3.1.tar.gz

  2. 解压并进入目录:tar -zxvf ffmpeg-3.1.tar.gz && cd ffmpeg-3.1

  3. 编译安装: ./configure && make && make install


在进行./configure操作的时候,可能出现yasm/nasm not found or too old. Use --disable-yasm for a crippledbuild错误。


yasm 是汇编编译器,ffmpeg 为了提高效率使用了汇编指令,如 MMX 和 SSE 等。所以系统中未安装 yasm 时,就会报错误,此时可以安装 yasm 编译器来解决:


  1. 下载wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz

  2. 解压并进入目录:tar zxvf yasm-1.3.0.tar.gz && cd yasm-1.3.0

  3. 编译安装:./configure && make && make install


完成 ffmpeg 的编译安装,就可以在当前目录下看到生成了文件:ffmpeg,此时我们保存这个文件即可在腾讯云的云函数中使用。

Serverless 架构下的视频压缩

按照腾讯云提供的实践架构图,其推荐的是对象存储触发器触发函数,也就是说我们将视频存储到对象存储中,然后通过对象存储的相关触发器触发函数进行视频的处理,处理之后再回传对象存储的操作。


代码实现:


import osimport subprocessfrom qcloud_cos_v5 import CosConfigfrom qcloud_cos_v5 import CosS3Client
secret_id = os.environ.get('secret_id')secret_key = os.environ.get('secret_key')region = os.environ.get('region')cosClient = CosS3Client(CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key))
# 移动ffmpeg到tmp目录,并且赋予权限with open("./ffmpeg", "rb") as rf: with open("/tmp/ffmpeg", "wb") as wf: wf.write(rf.read())subprocess.run('chmod 755 /tmp/ffmpeg', shell=True)
def main_handler(event, context):
for record in event['Records']: bucket = record['cos']['cosBucket']['name'] + '-' + record['cos']['cosBucket']['appid'] key = "/".join(record['cos']['cosObject']['key'].split("/")[3:]) download_path = '/tmp/{}'.format(key.split('/')[-1]) upload_path = '/tmp/new_mp4-{}'.format(key.split('/')[-1])
# 下载图片 print("key", key) response = cosClient.get_object(Bucket=bucket, Key=key) response['Body'].get_stream_to_file(download_path)
# 执行ffmpeg指令压缩视频 child = subprocess.run('/tmp/ffmpeg -i %s -r 10 -b:a 32k %s'%(download_path, upload_path), stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True, shell=True)
# 上传图片 cosClient.put_object_from_local_file( Bucket=bucket, LocalFilePath=upload_path, Key="/new_mp4/" + key.split('/')[-1] )

复制代码


这里的主要操作就是在容器建立的时候,或者说是函数冷启动的时候,将 ffmpeg 复制到可执行目录,并且设置其权限为755


完成之后可以进行serverless.yaml的编写:


MyVideo:  component: "@serverless/tencent-scf"  inputs:    name: MyVideo    codeUri: ./    handler: index.main_handler    runtime: Python3.6    region: ap-guangzhou    memorySize: 128    timeout: 200    environment:      variables:        secret_id: 用户密钥id        secret_key: 用户密钥key        region: ap-guangzhou    events:      - cos:          name: video-1256773370.cos.ap-guangzhou.myqcloud.com          parameters:            bucket: video-1256773370.cos.ap-guangzhou.myqcloud.com            filter:              prefix: source/            events: cos:ObjectCreated:*            enable: true
复制代码


部署完成,我们将一个测试的 MP4 文件上传到对应的存储的source/文件夹中:



稍等片刻,我们可以看到目标文件夹出现了对应的视频:



大家可以对比一下两个视频文件的差距。


当然,这里仅仅是通过/tmp/ffmpeg -i 原视频 -r 10 -b:a 32k 生成视频来进行视频压缩,除此之外,我们还可以使用 ffmpeg 进行额外的操作(以下内容来源于 canmeng 的博客):


ffmpeg -ss 00:00:00 -t 00:00:30 -i test.mp4 -vcodec copy -acodec copy output.mp4
复制代码


-ss 指定从什么时间开始

-t 指定需要截取多长时间

-i 指定输入文件


这个命令就是从 00 秒开始裁剪到 00+30=30 秒结束,总共 30 秒的视频。这个命令执行很快,因为只是原始数据的拷贝,中间没有什么编码和解码的过程,命令执行后可以得到 output.mp4 输出文件。


与期望的视频裁剪后的效果一致,00 秒开始,30 秒结束,总共 30 秒的视频,但是有些视频裁剪后你会发现开始和结束时间可能不是很准确,有可能是从 00 秒开始,33 秒结束。这是为什么呢?


因为这些视频里 30 秒处地方刚好不是关键帧,而 ffmpeg 会在你输入的时间点附近圆整到最接近的关键帧处,然后做接下来的事情。如果你不懂什么是关键帧,没关系,这也不影响你使用这个命令。


合并视频


//截取从头开始的30sffmpeg -ss 00:00:00 -t 00:00:30 -i keyoutput.mp4 -vcodec copy -acodec copy split.mp4//截取从30s开始的30sffmpeg -ss 00:00:30 -t 00:00:30 -i keyoutput.mp4 -vcodec copy -acodec copy split1.mp4//进行视频的合并ffmpeg -f concat -i list.txt -c copy concat.mp4
复制代码


在 list.txt 文件中,对要合并的视频片段进行了描述。


内容如下


file ./split.mp4file ./split1.mp4
复制代码


更多常用命令:


ffmpeg -i in.mp4 -filter:v "crop=in_w:in_h-40" -c:a copy out.mp4// 去掉视频中的音频ffmpeg -i input.mp4 -vcodec copy -an output.mp4// -an: 去掉音频;-vcodec:视频选项,一般后面加copy表示拷贝 // 提取视频中的音频ffmpeg -i input.mp4 -acodec copy -vn output.mp3// -vn: 去掉视频;-acodec: 音频选项, 一般后面加copy表示拷贝 // 音视频合成ffmpeg -y –i input.mp4 –i input.mp3 –vcodec copy –acodec copy output.mp4// -y 覆盖输出文件 //剪切视频ffmpeg -ss 0:1:30 -t 0:0:20 -i input.mp4 -vcodec copy -acodec copy output.mp4// -ss 开始时间; -t 持续时间 // 视频截图ffmpeg –i test.mp4 –f image2 -t 0.001 -s 320x240 image-%3d.jpg// -s 设置分辨率; -f 强迫采用格式fmt; // 视频分解为图片ffmpeg –i test.mp4 –r 1 –f image2 image-%3d.jpg// -r 指定截屏频率 // 将图片合成视频ffmpeg -f image2 -i image%d.jpg output.mp4 //视频拼接ffmpeg -f concat -i filelist.txt -c copy output.mp4 // 将视频转为gifffmpeg -i input.mp4 -ss 0:0:30 -t 10 -s 320x240 -pix_fmt rgb24 output.gif// -pix_fmt 指定编码 // 将视频前30帧转为gifffmpeg -i input.mp4 -vframes 30 -f gif output.gif // 旋转视频ffmpeg -i input.mp4 -vf rotate=PI/2 output.mp4 // 缩放视频ffmpeg -i input.mp4 -vf scale=iw/2:-1 output.mp4// iw 是输入的宽度, iw/2就是一半;-1 为保持宽高比 //视频变速ffmpeg -i input.mp4 -filter:v setpts=0.5*PTS output.mp4 //音频变速ffmpeg -i input.mp3 -filter:a atempo=2.0 output.mp3 //音视频同时变速,但是音视频为互倒关系ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" output.mp4 // 视频添加水印ffmpeg -i input.mp4 -i logo.jpg -filter_complex [0:v][1:v]overlay=main_w-overlay_w-10:main_h-overlay_h-10[out] -map [out] -map 0:a -codec:a copy output.mp4// main_w-overlay_w-10 视频的宽度-水印的宽度-水印边距; // 截取视频局部ffmpeg -i in.mp4 -filter:v "crop=out_w:out_h:x:y" out.mp4// 截取部分视频,从[80,60]的位置开始,截取宽200,高100的视频ffmpeg -i in.mp4 -filter:v "crop=80:60:200:100" -c:a copy out.mp4// 截取右下角的四分之一ffmpeg -i in.mp4 -filter:v "crop=in_w/2:in_h/2:in_w/2:in_h/2" -c:a copy out.mp4// 截去底部40像素高度ffmpeg -i in.mp4 -filter:v "crop=in_w:in_h-40" -c:a copy out.mp4

复制代码


参数说明:


-vcodec xvid 使用 xvid 压缩

-s 320×240 指定分辨率

-r fps 设置帧频 缺省 25

-b <比特率> 指定压缩比特

-acodec aac 设定声音编码

-ac <数值> 设定声道数,1 就是单声道,2 就是立体声

-ar <采样率> 设定声音采样率,PSP 只认 24000

-ab <比特率> 设定声音比特率

-vol <百分比> 设定音量

-y 覆盖输出文件

-t duration 设置纪录时间 hh:mm:ss[.xxx]格式的记录时间也支持

-ss position 搜索到指定的时间 [-]hh:mm:ss[.xxx]的格式也支持

-title string 设置标题

-author string 设置作者

-copyright string 设置版权

-hq 激活高质量设置

-aspect aspect 设置横纵比 4:3 16:9 或 1.3333 1.7777

-croptop size 设置顶部切除带大小 像素单位

-cropbottom size -cropleft size -cropright size

-padtop size 设置顶部补齐的大小 像素单位

-padbottom size -padleft size -padright size -padcolor color 设置补齐条颜色(hex,6 个 16 进制的数,红:绿:兰排列,比如 000000 代表黑色)

-bt tolerance 设置视频码率容忍度 kbit/s

-maxrate bitrate 设置最大视频码率容忍度

-minrate bitreate 设置最小视频码率容忍度

-bufsize size 设置码率控制缓冲区大小

-vcodec codec 强制使用 codec 编解码方式。 如果用 copy 表示原始编解码数据必须被拷贝

-sameq 使用同样视频质量作为源(VBR)

-pass n 选择处理遍数(1 或者 2)。两遍编码非常有用。第一遍生成统计信息,第二遍生成精确的请求的码率

-passlogfile file 选择两遍的纪录文件名为 file

-map file:stream 设置输入流映射

-debug 打印特定调试信息

总结

Serverless 架构不仅在同步业务方面能取得不错的效果,而且在异步流程上也有很棒的表现,因此可以通过 Serverless 架构来实现大数据分析,也可以实现图像压缩、水印/格式转换、视频处理。


2020-06-10 09:253850

评论

发布
暂无评论
发现更多内容

五分钟看穿Java并发相关概念,并发原来如此简单,linux学习步骤

Java 后端

京东T7架构师手写的10万字Spring Boot详细学习笔记+源码免费下载

Java 程序员 后端

什么是 MySQL 全局锁、表锁、行锁,Java高级开发岗必问知识点

Java 程序员 后端

今年,我在字节跳动面试了九次【已意向书,mongodb入门pdf

Java 程序员 后端

从Mybatis源码到Spring动态数据源底层原理分析系列二、Mybatis执行器源码分析

Java 程序员 后端

五分钟带你了解Seata分布式事务,java基础菜鸟教程txt

Java 程序员 后端

什么神仙笔记!阿里P9用39实例+1项目讲明白了Spring Cloud家族

Java 程序员 后端

从Mybatis源码到Spring动态数据源底层原理分析系列一、Mybatis初始化源码浅析

Java 程序员 后端

Vue进阶(幺伍伍):vue-resource 拦截器 interceptors 使用

No Silver Bullet

Vue vue-resource 10月月更

京东三面被惨虐:索引+数据库,kafka入门与实践epub

Java 程序员 后端

京东前端面经(123面详细),进阶学习工作最全指南

Java 程序员 后端

CANN 5.0黑科技解密 | 算力虚拟化,让AI算力“物尽其用”

华为云开发者联盟

AI 算力 CANN 昇腾 算力虚拟化

互联网寒冬下!疫情又遭滑铁卢!从裁员到斩获新offer我经历了什么

Java 程序员 后端

从一次线下读书会获得的收获,linux使用教程

Java 程序员 后端

京东面试,这个问题让我与50万擦肩而过,帮忙看看,mysql下载教程window10

Java 程序员 后端

人性的弱点-读书笔记,java面试题大汇总小山博客

Java 程序员 后端

什么?这个岗位薪资秒杀一众程序员?,java技术面试常见问题

Java 程序员 后端

从单体式架构迁移到微服务架构,3年Java开发工程师面试经验分享

Java 程序员 后端

架构实战营-毕业总结

王晓宇

架构实战营

二面余额宝(交叉面),mybatis功能架构

Java 程序员 后端

京东十年T8架构师手撕MySQL:手写666页核心知识,超85,java在线编译器实现原理

Java 程序员 后端

人到中年的焦虑,Java面试第一问就是做过什么最有难度的项目

Java 程序员 后端

今日头条一面:十道经典面试题解析,Redis如何实现高可扩展

Java 程序员 后端

从Java小白到拿到30k offer,分享自己的学习路程,java基础案例教程pdf百度云

Java 程序员 后端

五位阿里大牛联手撰写的《深入浅出Java多线程》,java开发视频直播

Java 程序员 后端

京东T9裂墙力荐的82万字spring cloud微服务和分布式系统实践文档

Java 程序员 后端

人工智能 - 语音识别的技术原理是什么,Java理论知识思维导图

Java 程序员 后端

互联网架构“高并发”到底怎么玩,用Elasticsearch搞定日均1亿订单查询

Java 程序员 后端

什么是接口的幂等性,如何实现接口幂等性?,java微服务架构视频下载

Java 程序员 后端

从 0 到 1,带你解剖 MVP 的神秘之处,并自己动手实现 MVP !

Java 程序员 后端

从小公司跳槽到阿里,靠着刷多套面试题,成功拿到蚂蚁金服P7Offer

Java 程序员 后端

Serverless实战:分分钟实现视频压缩与格式转换_服务革新_刘宇_InfoQ精选文章