介紹
本示例介紹了如何截取視頻的一段內(nèi)容制作gif圖片。該場景多出現(xiàn)在長視頻類應(yīng)用。使用FFmpeg命令對視頻進(jìn)行截取gif圖。
效果圖預(yù)覽
使用說明:
- 點擊“本地視頻截取gif”或“在線視頻截取gif”的視頻,進(jìn)入視頻播放頁面。
- 在視頻播放頁面中點擊“gif”按鈕,進(jìn)入視頻截取gif圖頁面。
- 可以拖動底部時間軸的選中框來選取需要截取的gif的片段,然后點擊“下一步”按鈕,進(jìn)入gif圖生成頁面。
- 在gif圖生成頁面稍等片刻會生成gif圖片,可以將gif圖保存至相冊。
實現(xiàn)步驟
- 打開視頻播放頁面,根據(jù)視頻是本地視頻還是線上視頻選擇設(shè)置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;
}
- 根據(jù)視頻播放頁面上"gif"按鈕的時間點,按一定規(guī)則確定截取的時間范圍,進(jìn)入選取生成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);
- 點擊"下一步"按鈕,會出現(xiàn)gif生成頁面,根據(jù)起始時間和截取長度通過MP4Parser的ffmpegCmd方法生成gif圖片。
MP4Parser.ffmpegCmd("ffmpeg -i " + srcFilePath + " -ss " + startTime + " -t " + duration + " " + dst, callBack);
高性能知識點
不涉及
工程結(jié)構(gòu)&模塊類型
videocreategif // har
|---components
| |---CustomLoadingDialog.ets // 自定義等待彈窗
| |---GifCreateView.ets // gif生成頁面
| |---RangeSeekBarView.ets // 時間軸選中框
| |---SelectGifTimeFrameView.ets // 選取生成gif時間片段頁面
| |---VideoThumbListView.ets // 時間軸小圖展示
|---model
| |---BannerInfo.ets // banner信息
| |---GlobalProxyServer.ets // 邊緩存邊播放服務(wù)器管理
| |---VideoInfo.ets // 視頻信息
|---util
| |---Logger.ets // 日志打印工具
| |---TimeTools.ets // 時長數(shù)據(jù)轉(zhuǎn)換工具
|---view
| |---VideoCreateGif.ets // 視頻項展示頁面
| |---VideoPlayPage.ets // 視頻播放頁面
寫在最后
- 如果你覺得這篇內(nèi)容對你還蠻有幫助,我想邀請你幫我三個小忙:
- 點贊,轉(zhuǎn)發(fā),有你們的 『點贊和評論』,才是我創(chuàng)造的動力。
- 關(guān)注小編,同時可以期待后續(xù)文章ing??,不定期分享原創(chuàng)知識。
- 想要獲取更多完整鴻蒙最新學(xué)習(xí)知識點,請移步前往小編:
https://gitee.com/MNxiaona/733GH/blob/master/jianshu