鸿蒙开发实战案例:视频截取gif图
本文介绍了如何使用FFmpeg命令截取视频片段生成GIF图片的功能实现方案。主要内容包括:1) 视频播放模块实现,区分本地和在线视频的处理方式;2) 通过MP4Parser获取视频帧展示在时间轴上;3) 时间轴选择框交互逻辑处理;4) GIF生成模块调用FFmpeg命令完成转换。文章还提供了完整的工程结构说明,包含视频播放、时间轴选择、GIF生成等核心模块的实现细节,以及在线视频边缓存边播放的处理
·
📝往期推文全新看点(文中附带最新·鸿蒙全栈学习笔记)
🚩 市场巨变,移动开发行业即将迎来“第二春”?
🚩 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?
🚩 嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~
🚩 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?
🚩 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?
🚩 记录一场鸿蒙开发岗位面试经历~
📃 持续更新中……
介绍
本示例介绍了如何截取视频的一段内容制作gif图片。该场景多出现在长视频类应用。使用FFmpeg命令对视频进行截取gif图。
效果图预览

使用说明:
- 点击“本地视频截取gif”或“在线视频截取gif”的视频,进入视频播放页面。
- 在视频播放页面中点击“gif”按钮,进入视频截取gif图页面。
- 可以拖动底部时间轴的选中框来选取需要截取的gif的片段,然后点击“下一步”按钮,进入gif图生成页面。
- 在gif图生成页面稍等片刻会生成gif图片,可以将gif图保存至相册。
实现步骤
- 打开视频播放页面,根据视频是本地视频还是线上视频选择设置avPlayer的url。如果是线上视频,使用边缓存边播放的方式,需要记录缓存文件的本地路径。
if (this.url.startsWith(getContext().filesDir)) {
this.srcFilePath = this.url;
let file = await fs.open(this.url);
this.avPlayer.url = `fd://${file.fd}`;
} else {
let that = this;
class MyCacheListener implements CacheListener {
onCacheAvailable(cacheFilePath: string, url: string, percentsAvailable: number): void {
AppStorage.setOrCreate('currentCachePercent', percentsAvailable);
if (!that.srcFilePath) {
// 记录缓存文件的本地路径
that.srcFilePath = cacheFilePath;
}
}
}
GlobalProxyServer?.getInstance()?.getServer()?.registerCacheListener(new MyCacheListener(), this.url);
let proxyUrl: string | undefined =
await GlobalProxyServer?.getInstance()?.getServer()?.getProxyUrl(this.url);
if (proxyUrl.startsWith(getContext().cacheDir)) {
this.srcFilePath = proxyUrl;
const file = fs.openSync(this.srcFilePath, fs.OpenMode.READ_ONLY);
proxyUrl = `fd://${file.fd}`;
}
this.avPlayer.url = proxyUrl;
}
- 根据视频播放页面上"gif"按钮的时间点,按一定规则确定截取的时间范围,进入选取生成gif时间片段页面,通过MP4Parser获取每秒的视频帧图片,展示在时间轴上。
MP4Parser.getFrameAtTimeRang(startTimeUs, endTimeUs, MP4Parser.OPTION_CLOSEST, frameCallBack);
- 时间轴选择框框取范围处理,具体处理可以查看RangeSeekBarView.ets文件,
let touchXNew:number = this.clearUndefined(event?.offsetX);
let deltaX:number = touchXNew - this.touchXOld;
if (this.touchType == TouchType.TouchLeftThumb) {
this.leftThumbUpdate(deltaX);
this.onRangeValueChanged();
} else if (this.touchType == TouchType.TouchRightThumb) {
this.rightThumbUpdate(deltaX);
this.onRangeValueChanged();
} else if (this.touchType == TouchType.TouchMiddleThumb) {
if ((deltaX < 0 && this.leftThumbRect[0] > 0)
|| (deltaX > 0 && this.rightThumbRect[2] < this.componentMaxWidth)) {
this.leftThumbUpdate(deltaX);
this.rightThumbUpdate(deltaX);
this.onRangeValueChanged();
}
}
this.touchXOld = this.clearUndefined(event?.offsetX);
- 点击"下一步"按钮,会出现gif生成页面,根据起始时间和截取长度通过MP4Parser的ffmpegCmd方法生成gif图片。
MP4Parser.ffmpegCmd("ffmpeg -i " + srcFilePath + " -ss " + startTime + " -t " + duration + " " + dst, callBack);
高性能知识点
不涉及
工程结构&模块类型
videocreategif // har
|---components
| |---CustomLoadingDialog.ets // 自定义等待弹窗
| |---GifCreateView.ets // gif生成页面
| |---RangeSeekBarView.ets // 时间轴选中框
| |---SelectGifTimeFrameView.ets // 选取生成gif时间片段页面
| |---VideoThumbListView.ets // 时间轴小图展示
|---model
| |---BannerInfo.ets // banner信息
| |---GlobalProxyServer.ets // 边缓存边播放服务器管理
| |---VideoInfo.ets // 视频信息
|---util
| |---Logger.ets // 日志打印工具
| |---TimeTools.ets // 时长数据转换工具
|---view
| |---VideoCreateGif.ets // 视频项展示页面
| |---VideoPlayPage.ets // 视频播放页面

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)