WebAssembly视频检测在社区创作平台的落地与实践 | 得物技术

一、背景&现状

创作者服务平台作为得物为社区创作者提供的PC端视频发布入口,地位非常重要。且随着功能的升级迭代,用户群体也越来越多。但我们偶尔会收到如下反馈:

  • 视频损坏,无法播放
  • 视频模糊
  • 曝光度问题
  • 黑屏,只有声音,没有画面

黑屏.jpeg
黑屏,无法播放

低清晰度.jpeg
低清晰度

曝光异常.jpeg
曝光异常

黑屏只有声音.jpeg
黑屏,只有声音

视频的损坏不仅影响用户体验,还可能导致忠诚用户的流失。用户在浏览时看到错误反馈或者无法播放的视频,容易产生挫败感。

第二,流量的上涨导致此类case越来越多,据统计,自2024年4月份开始,通过创作者平台发布的视频可分发视频量较之前上涨多倍。

为提升视频发布的质量和用户体验,视频发布前的检测能力需尽快落地。

二、业界的做法

在视频内容平台兴盛的今天,视频上传和检测方面已经有了一些有力措施,以确保用户上传的视频质量,最大程度地减少损坏视频对用户体验和平台形象的影响,比如服务端检测,创作者在上传完视频后,会立即触发服务端检测功能,经过等待后会反馈给用户信息,不强卡发布。

这一方案是可行的,但也存在些弊端:

  • 需要视频上传完成才能拿到完整的文件流进行检测,通常在PC上传的视频文件很大,要等到传完作者才能知道自己的视频有问题,然后再上传,再检测
  • 帖子发布时间拉长,增加创作者的等待,从心智上会影响创作者的体验
  • 带宽成本

但这一方案有个优秀的点,如对涉黄、涉恐等元素的视频,能同时被检测到并且禁止分发。

三、得物音视频团队的方案

目前得物音视频团队在上传前的预检测这种场景下已有了一套较为完善的方案,那就是使用C+ffmpeg编写好检测代码后再通过Emscripten工具将其打包成WebAssembly的二进制文件使代码运行在web端。

音视频团队的方案.jpeg

目前这个方案的核心检测能力已应用在得物App发布工具场景使用,其能通过ffmpeg解析视频的元数据,获取其基本信息,如视频尺寸,码率等,能查找目标视频下的视频流,对音频和视频的AVPacket进行验证,检测文件是否损坏,时间轴是否存在异常等等。正常的流程如下:

正常的流程如下.jpeg

经过此过程的检测,我们可以排除绝大多数文件格式存在问题的视频文件,下面列出一些常见的文件结构存在问题或者格式不合规的视频:

1.文件的moov不存在

https://videocdn.poizon.com/creator/og/2386746172_96421a9fd8662a848fef2a62ffbc1e63_1730287081103_dur1208dur_w1080h1920.mp4

moov不存在.jpeg

2.视频帧的NAL结构异常

https://videocdn.poizon.com/creator/og/2376721105_6dc8f934807c2b62b2261227d2b6699b_1730284366880_dur27dur_w720h1280.mp4

NAL结构异常.jpeg

3.没有视频轨道

https://videocdn.poizon.com/app/sns-og/2024/video/1753839080_byte588513_dur35786_ed63cbac543fdbfe1d8afc098a5be0c6_1729117036244_du_android_w480h480.mp4

没有视频轨道.jpeg

除了可以检测视频文件是否存在问题之外,我们还可以通过预检测获取大量的视频相关的信息:

1.视频的基本信息

  • 宽高、帧率(是否是动态帧率)、码率
  • 旋转角度

2.色域信息

  • 是否是HDR、DP3色域
  • 是8bit/10bit/12bit/16bit

3.视频编码附加信息

  • 当前的视频是否是从其他平台上搬运而来的?
  • 当前的视频是否使用其他的剪辑工具导出的?
  • 我们可以通过识别视频中的metadata中的信息来分析当前的视频来自哪些平台的:

来自抖音.jpeg
来自抖音

来自微信.jpeg
来自微信

来自快手.jpeg
来自快手

综上所述,我们在上传前预检测阶段,可以得到视频的很多信息 + 检测视频是否存在结构问题和格式问题。

四、我们需要解决的问题

虽然整体链路方案非常完善,但是SDK实际落地到web端运行还存在一些问题。

内存泄漏

我们先做个压力测试,在不刷新页面的情况,看下网页端内存如何变化:

1.准备32个50MB以内的小视频,1个800MB的大视频,内存采样为每3s采样一次

2.通过一个个上传,内存占用一直在上升,当传入800MB视频进行检测时,内存占用直接飙升至3G,未被正确释放

旧版SDK内存占用情况.jpeg
旧版SDK压力测试内存占用情况

此时控制台报错,内存溢出,页面卡死,用户必须刷新页面才可继续操作。

内存溢出报错.jpeg
控制台内存溢出报错

array异常占用.jpeg
ArrayBuffer异常占用

大视频无法检测

传入1.9GB的视频文件,控制台直接报错,无法申请1.9GB的内存。

大文件传入报错.jpeg
大文件传入报错

检测速度慢

一步步通过裁剪,缩小视频大小,800MB时视频传入检测成功,耗时94630ms。

五、内存优化方案

针对以上问题,我们一个个来看:

内存溢出:先了解下现有代码中内存是如何被分配和销毁的,下面是部分核心代码。

IO核心代码.jpeg
IO核心代码

大致的流程如下:

大致的流程如下.jpeg
通过流程图可见内存已经被正确的申请和释放了,但是实际表现确是申请的内存一直在被占用,所以可能不是代码逻辑问题,在翻阅了wasm官方设计文档时发现一个issue,其中提到了wasm内存设计方案存在几个问题(该issue还处于open状态):

wasm内存设计问题.jpeg
wasm内存设计问题

所以正是由于第2、3点导致了wasm占用的内存只能被扩大,而无法通过释放被缩小,一旦过多的使用malloc内存占用达到wasm的最大内存限制后,申请必将失败,后续的链路也就无法继续了。那么排除其他因素,通过代码验证一下吧,我们只需要将extract_video_data函数修改一下,直接释放掉接收的内存指针指向的内存块:

修改代码片段.jpeg
修改代码片段

依旧还是之前的物料进行压力测试,可见内存整体增长情况态势与之前别无二致,所以基本可以确认,内存一直占用的问题是wasm底层Memory的设计导致的,所以malloc函数我们肯定是用不了了。

验证内存采集.jpeg
验证内存采集

大视频无法检测:通过分析"IO核心代码"一图可以看到,视频文件是转成ArrayBuffer后通过forEach把一个个的字节塞入了提前申请好的内存中来实现数据传递的,这种方案存在两个问题:

  1. 效率低,不考虑文件转ArrayBuffer的时间,光遍历动不动就上百兆量级的buffer需要的时间都是巨量的,经过测试800MB文件想要全部转化为Uint8ClampedArray,然后写入到wasm内存中耗时大约在14秒左右,这就是导致检测速度慢的一个原因。

  2. ArrayBuffer的size是存在最大限制的,以chrome为例,这个限制是2GB,导致在js侧检测视频理论大小限制为了2GB,wasm侧最大可申请内存也存在限制,大约在1.6GB左右。在使用malloc申请到内存空间后又将其传入avio_alloc_context,avio_alloc_context内部将再次申请buffer_size大小的内存空间进行数据缓存, 从而导致实际检测视频最大为800MB。

所以ArrayBuffer这种方案是不能使用的,天然存在限制。那么到此问题原因都找到了,归根结底都出在文件的IO上,那么是否可以换一种思路,如果不需要任何的数据格式的转换,使wasm环境下的ffmpeg直接读取到文件这样肯定是最省时且高效的。那么ffmpeg能直接读取文件吗,答案是肯定的。

答案是肯定的.jpeg

avformat_open_input可以传入文件路径并能将AVFormatContext自动分配并写入ps。意思是只要能拿到目标文件的文件路径,就能直接调用avformat_open_input读取文件到IOContext,省去了将数据手动塞入IOContext的逻辑,也就意味着能绕过多余的内存的申请和释放,且不再需要进行数据格式的转换,可是怎样才能拿到目标文件路径呢?

因为SDK的运行环境是在web端,web端想要访问本地文件只能通过file类型的input拿到文件对象,那传入blobUrl行不行呢,经过测试,传入blobUrl会报Permission denied 无权限的错误,因为wasm的文件系统有自己的特殊实现,其并不能与JavaScript 直接进行交互,读取文件需要通过nodefs.js,idbfs.js,workerfs.js,proxyfs.js这几个js分别构造的虚拟文件系统才行,其分别是:

  • NODEFS,在node环境中使用的文件系统
  • IDBFS,在web浏览器中可使用的文件系统,强依赖IndexedDB
  • WORKERFS,工作在web浏览器,且只能运行在webWorker中的文件系统
  • PROXYFS,允许通过代理的方式访问本地文件系统或远程文件系统,主要用于将文件操作传递到JavaScript中的其他实现。这种机制使得WebAssembly模块能够与JavaScript代码进行交互,进而访问不同的文件系统或数据源

由此看来想要提供给avformat_open_input目标文件的路径,我们还需将目标文件挂载到一个虚拟文件系统中。那么该如何选择呢?

因为我们的SDK是需要运行在web浏览器中,那么NODEEFS首先就被排除掉了,其次视频的读取检测属于计算密集型任务,是需要运行在webWorker中的,所以WORKERFS与我们的使用场景更加契合,他提供对webWorker中的file和Blob对象的只读访问,而无需将整个数据复制到内存中,非常适合对大型文件的读取,也满足了我们对于快速读取和内存占用少的要求,简直完美。

那么说干就干,webWorker + WORKERFS的方案需要对打包命令和代码进行改造。首先启用WORKERFS需要在wasm的打包命令中添加-l workerfs.js参数,并且导出运行时函数WORKERFS,完整命令如下:

emcc -O3 \
-I ${FFMPEG_DIST_DIR}/include \
-L ${FFMPEG_DIST_DIR}/lib -l avcodec -l avformat -l swresample -l avutil -l workerfs.js\
-I ${CJSON_SOURCE_DIR} \
-s EXPORTED_FUNCTIONS="['_get_video_info', '_extract_video_data']" \
-s WASM=1 \
-s ALLOW_MEMORY_GROWTH=1 \
-s EXPORTED_RUNTIME_METHODS=[\"wasmMemory\", \"FS\", \"WORKERFS\", \"ccall\"]"
-fsanitize=address \
-o ${workspaceFolder}/sociality/main.js ${workspaceFolder}/sociality/main.c \
${CJSON_SOURCE_DIR}/cJSON.c ${CJSON_SOURCE_DIR}/cJSON_Utils.c

如果导出成功就能在wasm模块中看到WORKERFS的实例:

worker实例.jpeg

导出成功后想要使用的话只需要在webworker中创建任意文件夹,将目标文件通过mount方法挂载到该文件夹上就行,直接上代码:

webwork使用.jpeg
WORKERFS在Webworker中的使用

然后修改C语言侧extract_video_data方法:

修改c语言侧.jpeg

文件就能正确地被读取和处理了。可见这个方案非常的简洁且省去了巨量的IO操作,效率提升了,但是内存占用问题还存不存在呢,再次跑个压力测试试一试:

老SDK占用情况.jpeg
对比老SDK内存占用情况

用同样的视频物料进行压力测试,得出的内存占用情况如图,可见优化后内存使用在压力测试后一直维持在900MB左右,且继续传入大视频文件不会继续上涨,判断为正常内存占用(绿色线条),检测速度也做了一个粗略的统计,与旧版SDK对比,性能方面,以800MB文件为例,检测时长分别为20s和95s,性能预计提升约78%;2GB视频文件检测时长为61s,对于更大的视频也能轻松应对。至此所有的问题都已解决。目前该功能已上线:得物创作者平台。

六、总结

通过WebAssembly技术的引入与整合,我们在视频损坏检测上迎来了新的机遇。在逐步解决技术挑战的过程中,完善了我们的视频上传流程,并提升了用户体验。展望未来,我们希望继续优化这些功能,确保用户能够在平台上无障碍地上传和分享他们的创作,进一步提升社区的活跃度和用户粘性。

文 / 佳庆&ALBERT

关注得物技术,每周更新技术干货

要是觉得文章对你有帮助的话,欢迎评论转发点赞~

未经得物技术许可严禁转载,否则依法追究法律责任。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/958959.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Poetry shell --> poetry-plugin-shell

当前环境:Poetry (version 2.0.1) python Python 3.11.8 根据:https://python-poetry.org/docs/managing-environments/#bash-csh-zsh 在新版本的 poetry 执行 poetry shell 会报错 这个功能目前需要使用 poetry-plugin-shell 插件 关于 poetry-plugin-s…

《论文翻译》KIMI K1.5:用大语言模型扩展强化学习

文章目录 KIMI K1.5技术报告摘要 1. 引言2. 方法:基于大语言模型的强化学习2.1 强化学习提示集整理2.2 长思维链监督微调2.3 强化学习2.3.1 问题设定2.3.2 策略优化2.3.3 长度惩罚2.3.4 采样策略2.3.5 训练方法的更多细节 2.4 长到短:短思维链模型的上下…

Linux 安装 Nirgam

目录 Linux 安装 Nirgam声明安装 错误修正⭐修正后需要重新编译 参考资料 Linux 安装 Nirgam 声明 ⭐make失败调整重试前一定先 make clean 一下!!!特别感谢一篇博客园的博客(参考文献1),帮我解决了很多问…

分享一款开源好用的博客管理系统

ThriveX 现代化博客管理系统 🎉 🔥 首先最重要的事情放第一 开源不易,麻烦占用 10 秒钟的时间帮忙点个免费的 Star,再此万分感谢! 下面开始进入主题↓↓↓ 🌈 项目介绍: Thrive 是一个简而不…

Kafka 深入服务端 — 时间轮

Kafka中存在大量的延迟操作,比如延时生产、延时拉取和延时删除等。Kafka基于时间轮概念自定义实现了一个用于延时功能的定时器,来完成这些延迟操作。 1 时间轮 Kafka没有使用基于JDK自带的Timer或DelayQueue来实现延迟功能,因为它们的插入和…

九、CSS工程化方案

一、PostCSS介绍 二、PostCSS插件的使用 项目安装 - npm install postcss-cli 全局安装 - npm install postcss-cli -g postcss-cli地址:GitHub - postcss/postcss-cli: CLI for postcss postcss地址:GitHub - postcss/postcss: Transforming styles…

FFPlay命令全集合

FFPlay是以FFmpeg框架为基础,外加渲染音视频的库libSDL构建的媒体文件播放器。 ffplay工具下载并播放视频,可以辅助卡看流信息。 官网下载地址:http://ffmpeg.org/download.html#build-windows 下载build好的exe程序: 此处下载…

wangEditor富文本编辑器,Laravel上传图片配置和使用

文章目录 前言步骤1. 构造好前端模版2. 搭建后端存储3. 调试 前言 由于最近写项目需要使用富文本编辑器,使用的是VUE3.0版本所以很多不兼容,实际测试以后推荐使用wangEditor 步骤 构造好前端模版搭建后端存储调试 1. 构造好前端模版 安装模版 模版安…

利用 SAM2 模型探测卫星图像中的农田边界

将 Segment Anything Model Version 2 应用于卫星图像以检测和导出农业地区田地边界的分步教程 🌟 简介 手动绘制田地边界是最耗时的任务之一,其准确性取决于绘制者的表现。然而,精确的边界检测在很多领域都有应用。例如,假设您…

数据库管理-第287期 Oracle DB 23.7新特性一览(20250124)

数据库管理287期 20245-01-24 数据库管理-第287期 Oracle DB 23.7新特性一览(20250124)1 AI向量搜索:算术和聚合运算2 更改Compatible至23.6.0,以使用23.6或更高版本中的新AI向量搜索功能3 Cloud Developer包4 DBMS_DEVELOPER.GET…

第13章 深入volatile关键字(Java高并发编程详解:多线程与系统设计)

1.并发编程的三个重要特性 并发编程有三个至关重要的特性,分别是原子性、有序性和可见性 1.1 原子性 所谓原子性是指在一次的操作或者多次操作中,要么所有的操作全部都得到了执行并 且不会受到任何因素的干扰而中断,要么所有的操作都不执行…

mysql-06.JDBC

目录 什么是JDBC: 为啥存在JDBC: JDBC工作原理: JDBC的优势: 下载mysql驱动包: 用java程序操作数据库 1.创建dataSource: 2.与服务端建立连接 3.构造sql语句 4.执行sql 5.关闭连接,释放资源 参考代码: 插…

unity 粒子系统设置触发

1、勾选Triggers选项 2、将作为触发器的物体拉入队列当中,物体上必须挂载collider 3、将想要触发的方式(Inide、Outside、Enter和Exit)选择为”Callback“,其他默认为”Ignore“ 4、Collider Query Mode 设置为All&#xff1a…

LMI Gocator GO_SDK VS2019引用配置

LMI SDK在VS2019中的引用是真的坑爹,总结一下经验,希望后来的人能少走弯路.大致内容如下: (1) 环境变量 (2)C/C 附加包含目录 E:\GWQ\Gocator\GO_SDK\Gocator\GoSdk E:\GWQ\Gocator\GO_SDK\Platform\kApi (3&#…

61,【1】BUUCTF WEB BUU XSS COURSE 11

进入靶场 左边是吐槽,右边是登录,先登录试试 admin 123456 admiin# 123456 admin"# 123456 不玩了,先去回顾下xss 回顾完就很尴尬了,我居然用SQL的知识去做xss的题 重来 吐槽这里有一个输入框,容易出现存储型…

EchoMimicV2的部署使用

最近有一个录课的需要,我不想浪费人力,只想用技术解决。需求很简单,就是用别人现成的录课视频中的形象和声线,再结合我提供的讲稿去生成一个新的录课视频。我觉得应该有现成的技术了,我想要免费大批量生产。最近看到这…

五、华为 RSTP

RSTP(Rapid Spanning Tree Protocol,快速生成树协议)是 STP 的优化版本,能实现网络拓扑的快速收敛。 一、RSTP 原理 快速收敛机制:RSTP 通过引入边缘端口、P/A(Proposal/Agreement)机制等&…

嵌入式知识点总结 ARM体系与架构 专题提升(四)-编程

针对于嵌入式软件杂乱的知识点总结起来,提供给读者学习复习对下述内容的强化。 目录 1.嵌人式编程中,什么是大端?什么是小端 ? 2.如何判断计算机处理器是大端,还是小端 ? 3.如何进行大小端的转换 ? 4.如何对绝对地址0x100000赋值? 1…

Ansys Thermal Desktop 概述

介绍 Thermal Desktop 是一种用于热分析和流体分析的通用工具。它可用于组件或系统级分析。 来源:CRTech 历史 Thermal Desktop 由 C&R Technologies (CR Tech) 开发。它采用了 SINDA/FLUINT 求解器。SINDA/FLUINT 最初由 CR Tech 的创始人为 NASA 的约翰逊航…

Python vLLM 实战应用指南

文章目录 1. vLLM 简介2. 安装 vLLM3. 快速开始3.1 加载模型并生成文本3.2 参数说明 4. 实战应用场景4.1 构建聊天机器人示例对话: 4.2 文本补全输出示例: 4.3 自定义模型服务启动服务调用服务 5. 性能优化5.1 GPU 加速5.2 动态批处理 6. 总结 vLLM 是一…