概述
在手機、平板或是智慧屏這些終端設備上,媒體功能可以算作是我們最常用的場景之一。無論是實現音頻的播放、錄制、采集,還是視頻的播放、切換、循環,亦或是相機的預覽、拍照等功能,媒體組件都是必不可少的。以視頻功能為例,在應用開發過程中,我們需要通過ArkUI提供的Video組件為應用增加基礎的視頻播放功能。借助Video組件,我們可以實現視頻的播放功能并控制其播放狀態。常見的視頻播放場景包括觀看網絡上的較為流行的短視頻,也包括查看我們存儲在本地的視頻內容。
本文將結合《簡易視頻播放器(ArkTS)》這個Codelab,對Video組件的參數、屬性及事件進行介紹,然后通過組件的屬性調用和事件回調闡明Video組件的基本使用方法,最后結合Video組件使用過程中的常見問題講解自定義控制器的使用。
Video組件用法介紹
Video組件參數介紹 Video組件的接口表達形式為:
- Video(value: {src?: string | Resource, currentProgressRate?: number | string |PlaybackSpeed, previewUri?: string |PixelMap | Resource, controller?: VideoController})
其中包含四個可選參數,src、currentProgressRate、previewUri和controller。
- src表示視頻播放源的路徑,可以支持本地視頻路徑和網絡路徑。使用網絡地址時,如https,需要注意的是需要在module.json5文件中申請網絡權限。在使用本地資源播放時,當使用本地視頻地址我們可以使用媒體庫管理模塊medialibrary來查詢公共媒體庫中的視頻文件,示例代碼如下:
import mediaLibrary from '@ohos.multimedia.mediaLibrary';
async queryMediaVideo() {
let option = {
// 根據媒體類型檢索
selections: mediaLibrary.FileKey.MEDIA_TYPE + '=?',
// 媒體類型為視頻
selectionArgs: [mediaLibrary.MediaType.VIDEO.toString()]
};
let media = mediaLibrary.getMediaLibrary(getContext(this));
// 獲取資源文件
const fetchFileResult = await media.getFileAssets(option);
// 以獲取的第一個文件為例獲取視頻地址
let fileAsset = await fetchFileResult.getFirstObject();
this.source = fileAsset.uri
}
為了方便功能演示,示例中媒體資源需存放在resources下的rawfile文件夾里。
- currentProgressRate表示視頻播放倍速,其參數類型為number,取值支持0.75,1.0,1.25,1.75,2.0,默認值為1.0倍速;
- previewUri表示視頻未播放時的預覽圖片路徑;
- controller表示視頻控制器。
參數的具體描述如下表:
參數名 | 參數類型 | 必填 |
---|---|---|
src | string | Resource |
currentProgressRate | number | string |
previewUri | string | PixelMap8+ |
controller | VideoController | 否 |
說明
視頻支持的規格是:mp4、mkv、webm、TS。 下面我們通過具體的例子來說明參數的使用方法,我們選擇播放本地視頻,視頻未播放時的預覽圖片路徑也為本地,代碼實現如下:
@Component
export struct VideoPlayer {
private source: string | Resource;
private controller: VideoController;
private previewUris: Resource = $r('app.media.preview');
...
build() {
Column() {
Video({
src: this.source,
previewUri: this.previewUris,
controller: this.controller
})
...
VideoSlider({ controller: this.controller })
}
}
}
效果如下:
Video組件屬性介紹
除了支持組件的尺寸設置、位置設置等通用屬性外,Video組件還支持是否靜音、是否自動播放、控制欄是否顯示、視頻顯示模式以及單個視頻是否循環播放五個私有屬性。
名稱 | 參數類型 | 描述 |
---|---|---|
muted | boolean | 是否靜音。默認值:false |
autoPlay | boolean | 是否自動播放。默認值:false |
controls | boolean | 控制視頻播放的控制欄是否顯示。默認值:true |
objectFit | ImageFit | 設置視頻顯示模式。默認值:Cover |
loop | boolean | 是否單個視頻循環播放。默認值:false |
其中,objectFit 中視頻顯示模式包括Contain、Cover、Auto、Fill、ScaleDown、None 6種模式,默認情況下使用ImageFit.Cover(保持寬高比進行縮小或者放大,使得圖片兩邊都大于或等于顯示邊界),其他效果(如自適應顯示、保持原有尺寸顯示、不保持寬高比進行縮放等)可以根據具體使用場景/設備來進行選擇。 在Codelab示例中體現了controls、autoplay和loop屬性的配置,示例代碼如下:
@Component
export struct VideoPlayer {
private source: string | Resource;
private controller: VideoController;
...
build() {
Column() {
Video({
controller: this.controller
})
.controls(false) //不顯示控制欄
.autoPlay(false) // 手動點擊播放
.loop(false) // 關閉循環播放
...
}
}
}
效果如下:
Video組件回調事件介紹
Video組件能夠支持常規的點擊、觸摸等通用事件,同時也支持onStart、onPause、onFinish、onError等事件,具體事件的功能描述見下表:
事件名稱 | 功能描述 |
---|---|
onStart(event:() => void) | 播放時觸發該事件。 |
onPause(event:() => void) | 暫停時觸發該事件。 |
onFinish(event:() => void) | 播放結束時觸發該事件。 |
onError(event:() => void) | 播放失敗時觸發該事件。 |
onPrepared(callback:(event?: { duration: number }) => void) | 視頻準備完成時觸發該事件,通過duration可以獲取視頻時長,單位為s。 |
onSeeking(callback:(event?: { time: number }) => void) | 操作進度條過程時上報時間信息,單位為s。 |
onSeeked(callback:(event?: { time: number }) => void) | 操作進度條完成后,上報播放時間信息,單位為s。 |
onUpdate(callback:(event?: { time: number }) => void) | 播放進度變化時觸發該事件,單位為s,更新時間間隔為250ms。 |
onFullscreenChange(callback:(event?: { fullscreen: boolean }) => void) | 在全屏播放與非全屏播放狀態之間切換時觸發該事件 |
在Codelab中我們以更新事件、準備事件、失敗事件以及點擊事件為回調為例進行演示,代碼實現如下:
Video({ ... })
.onUpdate((event) = > {
this.currentTime = event.time;
this.currentStringTime = changeSliderTime(this.currentTime); //更新事件
})
.onPrepared((event) = > {
prepared.call(this, event); //準備事件
})
.onError(() = > {
prompt.showToast({
duration: COMMON_NUM_DURATION, //播放失敗事件
message: MESSAGE
});
...
})
其中,onUpdate更新事件在播放進度變化時觸發,從event中可以獲取當前播放進度,從而更新進度條顯示事件,比如視頻播放時間從24秒更新到30秒。onError事件在視頻播放失敗時觸發,在CommonConstants.ets中定義了常量類MESSAGE,所以在視頻播放失敗時會顯示“請檢查網絡”。
- const MESSAGE: string = '請檢查網絡'
自定義控制器的組成與實現
自定義控制器的組成
Video組件的原生控制器樣式相對固定,當我們對頁面的布局色調的一致性有所要求,或者在拖動進度條的同時需要顯示其百分比進度時,原生控制器就無法滿足需要了。如下圖右側的效果需要使用自定義控制器實現,接下來我們看一下自定義控制器的組成。
為了實現自定義控制器的進度顯示等功能,我們需要通過Row容器實現控制器的整體布局,然后借由Text組件來顯示視頻的播放起始時間、進度時間以及視頻總時長,最后通過滑動進度條Slider組件來實現視頻進度條的效果,代碼如下:
@Component
export struct VideoSlider {
...
build() {
Row(...) {
Image(...)
Text(...)
Slider(...)
Text(...)
}
...
}
}
自定義控制器的實現
自定義控制器容器內嵌套了視頻播放時間Text組件、滑動器Slider組件以及視頻總時長Text組件 3個橫向排列的組件,其中Text組件在之前的基礎組件課程中已經有過詳細介紹,這里就不再進行贅述。需要強調的是兩個Text組件顯示的時長是由Slider組件的onChange(callback: (value: number, mode: SliderChangeMode) => void)回調事件來進行傳遞的,而Text組件的數值與視頻播放進度數值value則是通過@Provide與 @Consume裝飾器進行的數據聯動,實現效果可見圖片下方黑色控制欄部分,具體代碼步驟及代碼如下: 獲取/計算視頻時長
export function prepared(event) {
this.durationTime = event.duration;
let second: number = event.duration % COMMON_NUM_MINUTE;
let min: number = parseInt((event.duration / COMMON_NUM_MINUTE).toString());
let head = min < COMMON_NUM_DOUBLE ? `${ZERO_STR}${min}` : min;
let end = second < COMMON_NUM_DOUBLE ? `${ZERO_STR}${second}` : second;
this.durationStringTime = `${head}${SPLIT}${end}`;
...
};
設置進度條參數及屬性
Slider({
value: this.currentTime,
min: 0,
max: this.durationTime,
step: 1,
style: SliderStyle.OutSet
})
.blockColor($r('app.color.white'))
.width(STRING_PERCENT.SLIDER_WITH)
.trackColor(Color.Gray)
.selectedColor($r('app.color.white'))
.showSteps(true)
.showTips(true)
.trackThickness(this.isOpacity ? SMALL_TRACK_THICK_NESS : BIG_TRACK_THICK_NESS)
.onChange((value: number, mode: SliderChangeMode) = > {...})
計算當前進度播放時間及添加onUpdate回調 最后,在我們播放視頻時還需要更新顯示播放的時間進度,也就是左側的Text組件。在視頻開始播放前,播放時間默認為00:00,隨著視頻播放,時間需要不斷更新為當前進度時間。所以左側的Text組件我們不僅需要讀取時間,還需要為其添加數據聯動。這里,我們就是通過為Video組件添加onUpdate事件來實現的,在視頻播放過程中會不斷調用changeSliderTime方法獲取當前的播放時間并進行計算及單位轉化,從而不斷刷新進度條的值,也就是控制器左側的播放進度時間Text組件。
Video({...})
...
.onUpdate((event) = > {
this.currentTime = event.time;
this.currentStringTime = changeSliderTime(this.currentTime)
})
export function changeSliderTime(value: number): string {
let second: number = value % COMMON_NUM_MINUTE;
let min: number = parseInt((value / COMMON_NUM_MINUTE).toString());
let head = min < COMMON_NUM_DOUBLE ? `${ZERO_STR}${min}` : min;
let end = second < COMMON_NUM_DOUBLE ? `${ZERO_STR}${second}` : second;
let nowTime = `${head}${SPLIT}${end}`;
return nowTime;
};
指定視頻播放進度及添加onChange事件回調 如需手動進行進度條的拖動,則需要在Slider組件中指定播放進度,并為Slider組件添加onChange事件回調。Slider滑動時就會觸發該事件回調,從而實現將視頻定位到進度條當前刷新位置,完成時長組件渲染與視頻播放進度數據聯動。
Slider({...})
.onChange((value: number, mode: SliderChangeMode) = > {
sliderOnchange.call(this, value, mode);
})
export function sliderOnchange(value: number, mode: SliderChangeMode) {
this.currentTime = parseInt(value.toString());
this.controller.setCurrentTime(parseInt(value.toString()), SeekMode.Accurate);
...
};
到這里我們就實現了自定義控制器的構建,兩個Text組件顯示的時長是由Slider組件的onChange回調事件來進行傳遞的,而Text組件的數值與視頻播放進度數值value則通過是onUpdate與onChange事件并借由@Provide @Consume裝飾器進行的數據聯動。
審核編輯 黃宇
-
存儲
+關注
關注
13文章
4266瀏覽量
85686 -
鴻蒙
+關注
關注
57文章
2321瀏覽量
42749
發布評論請先 登錄
相關推薦
評論