您的位置:首页 > 游戏 > 手游 > 嘉兴手机端建站模板_加快百度收录的方法_十大短视频平台排行榜_成都网络营销公司排名

嘉兴手机端建站模板_加快百度收录的方法_十大短视频平台排行榜_成都网络营销公司排名

2024/12/26 14:51:29 来源:https://blog.csdn.net/zouyang920/article/details/144208034  浏览:    关键词:嘉兴手机端建站模板_加快百度收录的方法_十大短视频平台排行榜_成都网络营销公司排名
嘉兴手机端建站模板_加快百度收录的方法_十大短视频平台排行榜_成都网络营销公司排名

目录:

    • 1、鸿蒙视频功能介绍
    • 2、AVPlayer组件实现视频播放
      • 2.1、播放功能的逻辑处理
      • 2.2、页面调用渲染
      • 2.3、缓存播放信息
    • 3、video组件实现视频播放
      • 3.1、鸿蒙官网实现代码
      • 3.2、通过xml布局文件代码实现
        • I. 创建项目
        • II. 定义布局文件
        • III. 实现音频和视频播放功能
        • IV. 音频播放实现
        • V. 视频播放实现

1、鸿蒙视频功能介绍

鸿蒙提供了两种方式实现视频播放功能:

  • 使用video组件实现视频播放
  • 使用AVPlayer组件实现视频播放

2、AVPlayer组件实现视频播放

2.1、播放功能的逻辑处理

import media from '@ohos.multimedia.media'export class VideoAVPlayerClass {// 创建的播放器应该存在我们的工具类上,这样才能被导出使用static player: media.AVPlayer | null = null// 当前播放器播放视频的总时长static duration: number = 0// 当前播放器播放的时长static time: number = 0// 当前播放器是否播放static isPlay: boolean = false// 当前播放器的播放列表static playList: videoItemType[] = []// 当前播放的视频索引static playIndex: number = 0// surfaceID用于播放画面显示,具体的值需要通过XComponent接口获取static surfaceId: string = ''// 播放器上记录上下文static context: Context|null = null// 创建播放器的方法static async init(initParams: InitParams) {// 存储属性SurfaceID,用于设置播放窗口,显示画面VideoAVPlayerClass.surfaceId = initParams.surfaceId// 将上下文 context 存储到播放器类上VideoAVPlayerClass.context = initParams.context// 创建播放器实例VideoAVPlayerClass.player = await media.createAVPlayer()// ----------------------- 事件监听 --------------------------------------------------------------// 用于进度条,监听进度条长度,刷新资源时长VideoAVPlayerClass.avPlayer.on('durationUpdate', (duration: number) => {console.info('AVPlayer state durationUpdate called. current time: ', duration);// 获取视频总时长VideoAVPlayerClass.duration = duration})// 用于进度条,监听进度条当前位置,刷新当前时间VideoAVPlayerClass.avPlayer.on('timeUpdate', (time) =>{console.info('AVPlayer state timeUpdate called. current time: ', time);// 获取当前播放时长VideoAVPlayerClass.time = time// 更新信息到页面VideoAVPlayerClass.updateState()})// 监听seek生效的事件VideoAVPlayerClass.avPlayer.on('seekDone', (seekDoneTime: number) => {console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);VideoAVPlayerClass.avPlayer.play()VideoAVPlayerClass.isPlay = true})// 监听视频播放错误事件,当avPlayer在操作过程中出现错误时调用reset接口触发重置流程VideoAVPlayerClass.avPlayer.on('error', (err) => {console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);// 调用reset重置资源,触发idle状态VideoAVPlayerClass.avPlayer.reset()})// 监听播放状态机AVPlayerState切换的事件VideoAVPlayerClass.avPlayer.on('stateChange', async (state: media.AVPlayerState, reason: media.StateChangeReason) => {switch (state) {// 成功调用reset接口后触发该状态机上报case 'idle':console.info('AVPlayer state idle called.');break// avplayer 设置播放源后触发该状态上报case 'initialized':console.info('AVPlayerstate initialized called.');// 设置显示画面,当播放的资源为纯音频时无需设置VideoAVPlayerClass.avPlayer.surfaceId = VideoAVPlayerClass.surfaceIdbreak// prepare调用成功后上报该状态机case 'prepared':console.info('AVPlayer state prepared called.');break// play成功调用后触发该状态机上报case 'playing':console.info('AVPlayer state playing called.');break// pause成功调用后触发该状态机上报case 'paused':console.info('AVPlayer state paused called.');break// 播放结束后触发该状态机上报case 'completed':console.info('AVPlayer state completed called.');// 当前视频播放完成,自动播放下一个视频哦if (VideoAVPlayerClass.autoPlayList && VideoAVPlayerClass.playIndex < VideoAVPlayerClass.playList.length) {VideoAVPlayerClass.playIndex++VideoAVPlayerClass.playIndex = (VideoAVPlayerClass.playIndex + VideoAVPlayerClass.playList.length) % VideoAVPlayerClass.playList.lengthVideoAVPlayerClass.singlePlay(VideoAVPlayerClass.playList[VideoAVPlayerClass.playIndex])VideoAVPlayerClass.isPlay = true} else {VideoAVPlayerClass.isPlay = false// 停止播放VideoAVPlayerClass.avPlayer.stop()}break// stop接口成功调用后触发该状态机上报case 'stopped':console.info('AVPlayer state stopped called.');// 调用reset接口初始化avplayer状态VideoAVPlayerClass.avPlayer.reset()breakcase 'released':console.info('AVPlayer state released called.');break;default:console.info('AVPlayer state unknown called.');break;}})}// 视频播放static async play() {VideoAVPlayerClass.avPlayer.play()VideoAVPlayerClass.isPlay = trueVideoAVPlayerClass.updateState()}// 视频暂停static pause() {VideoAVPlayerClass.avPlayer.pause()VideoAVPlayerClass.isPlay = falseVideoAVPlayerClass.updateState()}// 切换视频static singlePlay(video?: videoItemType) {if (video) {let index = VideoAVPlayerClass.playList.findIndex((item: videoItemType) => item.id === video.id)if (index > -1) {// 当前要播放的视频在播放列表里VideoAVPlayerClass.playIndex = index} else {// 当前要播放的视频不在播放列表里VideoAVPlayerClass.playList.push(video)VideoAVPlayerClass.playIndex = VideoAVPlayerClass.playList.length - 1}}VideoAVPlayerClass.changePlay()}static async changePlay() {// 将播放状态置为闲置await VideoAVPlayerClass.avPlayer.reset()// 重置当前播放时长和视频时长VideoAVPlayerClass.time = 0VideoAVPlayerClass.duration = 0VideoAVPlayerClass.avPlayer.url = VideoAVPlayerClass.playList[VideoAVPlayerClass.playIndex].urlVideoAVPlayerClass.updateState()}// 更新页面状态static async updateState() {const data = {playState: JSON.stringify({duration: VideoAVPlayerClass.duration,time: VideoAVPlayerClass.time,isPlay: VideoAVPlayerClass.isPlay,playIndex: VideoAVPlayerClass.playIndex,playList: VideoAVPlayerClass.playList,})}// 更新页面emitter.emit({eventId: EmitEventType.UPDATE_STATE}, {data})// 存储首选项const preferences:PreferencesClass = new PreferencesClass(VideoAVPlayerClass.context)await preferences.setVideoPlayState(JSON.parse(data.playState))}}

2.2、页面调用渲染

import emitter from '@ohos.events.emitter';
import PlayingAnimation from '../components/PlayingAnimation';
import { EmitEventType } from '../constants/EventContants';
import { VideoListData } from '../constants/VideoConstants';
import { PlayStateType, PlayStateTypeModel } from '../models/playState';
import { videoItemType } from '../models/video';
import { VideoPlayStateType, VideoPlayStateTypeModel } from '../models/videoPlayState';
import { PreferencesClass } from '../utils/PreferencesClass';
import { VideoAVPlayerClass } from '../utils/VideoAVPlayerClass';@Preview
@Component
struct Index {@StateplayState: VideoPlayStateType = new VideoPlayStateTypeModel({} as VideoPlayStateType)xComController: XComponentController = new XComponentController()surfaceId: string = "" // 定义surfaceIdvideoList: videoItemType[] = VideoListDataasync aboutToAppear() {// 从播放器订阅数据emitter.on({ eventId: EmitEventType.UPDATE_STATE }, (data) => {this.playState = new VideoPlayStateTypeModel(JSON.parse(data.data.playState))})// 从首选项加载数据const preferences:PreferencesClass = new PreferencesClass(getContext(this))this.playState = await preferences.getVideoPlayState()}aboutToDisappear(){// 销毁播放器VideoAVPlayerClass.avPlayer.release()}// 时长数字(ms)转字符串number2time(number: number) {if (!number) {return '00:00'}const ms: number = number % 1000const second = (number - ms) / 1000const s: number = second % 60if (second > 60) {const m: number = (second - s) / 60 % 60return m.toString().padStart(2, '0') + ':' + s.toString().padStart(2, '0')}return '00:' + s.toString().padStart(2, '0')}build() {Row() {Column({ space: 10 }) {Stack() {Column() {Row(){// 视频播放窗口XComponent({id: 'videoXComponent',type: 'surface',controller: this.xComController}).width('100%').height(200).onLoad(async () => {this.xComController.setXComponentSurfaceSize({ surfaceWidth: 1080, surfaceHeight: 1920 });this.surfaceId = this.xComController.getXComponentSurfaceId()if (this.surfaceId) {await VideoAVPlayerClass.init({surfaceId: this.surfaceId, playList: this.videoList, context: getContext(this)})await VideoAVPlayerClass.singlePlay()}})}.onClick(() => {this.playState.isPlay ? VideoAVPlayerClass.pause() : VideoAVPlayerClass.play()})// 进度条Row({space: 6}){// 当前播放时长Text(this.number2time(this.playState?.time)).fontColor($r('app.color.white')).visibility(this.playState?.duration ? Visibility.Visible : Visibility.Hidden)// 进度条Slider({value: this.playState.time,min: 0,max: this.playState.duration,}).trackColor($r('app.color.white')).onChange((value: number, mode: SliderChangeMode) => {// 切换播放进度VideoAVPlayerClass.seekTime(value)}).width("70%")// 视频总时长Text(this.number2time(this.playState?.duration)).fontColor($r('app.color.white')).visibility(this.playState?.duration ? Visibility.Visible : Visibility.Hidden)}.width('100%').height(20).margin({top: 10}).justifyContent(FlexAlign.Center)}.width('100%').height(270).padding({top: 30,bottom:30}).backgroundColor($r('app.color.black')).justifyContent(FlexAlign.Start)// 播放按钮if (!this.playState.isPlay) {Image($r('app.media.ic_play')).width(48).height(48).fillColor($r('app.color.white')).onClick(() => {VideoAVPlayerClass.play()})}}// 视频列表缩略图List({ space: 10, initialIndex: 0 }) {ForEach(this.videoList, (item: videoItemType, index: number) => {ListItem() {Stack({alignContent: Alignment.Center}){Image(item.imgUrl).width(100).height(80)// .objectFit(ImageFit.Contain)if (this.playState.playIndex === index) {Row(){PlayingAnimation({ recordIng: true })}}}}.width(100).onClick(() => {VideoAVPlayerClass.singlePlay(item)})}, item => item)}.height(100).listDirection(Axis.Horizontal) // 排列方向.edgeEffect(EdgeEffect.Spring) // 滑动到边缘无效果.onScrollIndex((firstIndex: number, lastIndex: number) => {console.info('first' + firstIndex)console.info('last' + lastIndex)})}.width('100%').height('100%')}.height('100%').width('100%')}
}export default Index

2.3、缓存播放信息

问题场景:
我们的播放器已经可以正常进行视频的播放和切换了,当我们不小心退出了当前页面,再进入播放页面时,你会发现我们当前播放的视频信息没有了,这是为什么呢?

在当前的实现中,播放页面的信息是通过订阅播放器得到的,如果不播放了,就没有了信息来源的渠道,所以页面的播放信息就没有了。因此我们需要再建立一个信息收集渠道,即使不在播放时,也能获取到最后的播放信息数据。为此,我们使用**@ohos.data.preferences(用户首选项)**来持久化播放信息。

实现一个存储和读取首选项的工具类:

import preferences from '@ohos.data.preferences'
import { videoDefaultState, VideoPlayStateType } from '../models/videoPlayState'export class PreferencesClass {StoreName = 'VIDEO_PLAYER'context: ContextVideoPlayStateKey = "VIDEO_PLAY_STATE"constructor(context: Context) {this.context = context}// 获取storeasync getStore() {return await preferences.getPreferences(this.context,this.StoreName)}// 存储视频播放状态async setVideoPlayState(playState:VideoPlayStateType){const store = await this.getStore()await store.put(this.PlayStateKey,JSON.stringify(playState))await store.flush()}// 读取视频播放状态async getVideoPlayState(): Promise<VideoPlayStateType> {const store = await this.getStore()return JSON.parse(await store.get(this.VideoPlayStateKey,JSON.stringify(videoDefaultState)) as string) as VideoPlayStateType}
}

3、video组件实现视频播放

3.1、鸿蒙官网实现代码

// xxx.ets
@Entry
@Component
struct VideoCreateComponent {@State videoSrc: Resource = $rawfile('video1.mp4')@State previewUri: Resource = $r('app.media.poster1')@State curRate: PlaybackSpeed = PlaybackSpeed.Speed_Forward_1_00_X@State isAutoPlay: boolean = false@State showControls: boolean = truecontroller: VideoController = new VideoController()build() {Column() {Video({src: this.videoSrc,previewUri: this.previewUri,currentProgressRate: this.curRate,controller: this.controller}).width('100%').height(600).autoPlay(this.isAutoPlay).controls(this.showControls).onStart(() => {console.info('onStart')}).onPause(() => {console.info('onPause')}).onFinish(() => {console.info('onFinish')}).onError(() => {console.info('onError')}).onStop(() => {console.info('onStop')}).onPrepared((e?: DurationObject) => {if (e != undefined) {console.info('onPrepared is ' + e.duration)}}).onSeeking((e?: TimeObject) => {if (e != undefined) {console.info('onSeeking is ' + e.time)}}).onSeeked((e?: TimeObject) => {if (e != undefined) {console.info('onSeeked is ' + e.time)}}).onUpdate((e?: TimeObject) => {if (e != undefined) {console.info('onUpdate is ' + e.time)}})Row() {Button('src').onClick(() => {this.videoSrc = $rawfile('video2.mp4') // 切换视频源}).margin(5)Button('previewUri').onClick(() => {this.previewUri = $r('app.media.poster2') // 切换视频预览海报}).margin(5)Button('controls').onClick(() => {this.showControls = !this.showControls // 切换是否显示视频控制栏}).margin(5)}Row() {Button('start').onClick(() => {this.controller.start() // 开始播放}).margin(2)Button('pause').onClick(() => {this.controller.pause() // 暂停播放}).margin(2)Button('stop').onClick(() => {this.controller.stop() // 结束播放}).margin(2)Button('reset').onClick(() => {this.controller.reset() // 重置AVPlayer}).margin(2)Button('setTime').onClick(() => {this.controller.setCurrentTime(10, SeekMode.Accurate) // 精准跳转到视频的10s位置}).margin(2)}Row() {Button('rate 0.75').onClick(() => {this.curRate = PlaybackSpeed.Speed_Forward_0_75_X // 0.75倍速播放}).margin(5)Button('rate 1').onClick(() => {this.curRate = PlaybackSpeed.Speed_Forward_1_00_X // 原倍速播放}).margin(5)Button('rate 2').onClick(() => {this.curRate = PlaybackSpeed.Speed_Forward_2_00_X // 2倍速播放}).margin(5)}}}
}interface DurationObject {duration: number;
}interface TimeObject {time: number;
}

3.2、通过xml布局文件代码实现

实现步骤:

I. 创建项目

打开 DevEco Studio,创建一个新的 HarmonyOS 项目,选择“Empty Ability”模板。

配置权限:

在项目的配置文件 config.json 中,添加存储权限。

 {"module": {"reqPermissions": [{"name": "ohos.permission.READ_STORAGE"},{"name": "ohos.permission.WRITE_STORAGE"}]}}
II. 定义布局文件

定义布局文件:

在 src/main/resources/base/layout 目录下,创建一个布局文件 ability_main.xml,用于展示音频播放和视频播放的控件。

<?xml version="1.0" encoding="utf-8"?><DirectionalLayoutxmlns:ohos="http://schemas.huawei.com/res/ohos"ohos:width="match_parent"ohos:height="match_parent"ohos:orientation="vertical"ohos:padding="16vp"><Videoohos:id="$+id/video_player"ohos:width="match_parent"ohos:height="200vp"ohos:layout_marginBottom="16vp"ohos:scale_type="centerCrop"/><Buttonohos:id="$+id/button_play_video"ohos:width="match_content"ohos:height="wrap_content"ohos:text="Play Video"/><Buttonohos:id="$+id/button_play_audio"ohos:width="match_content"ohos:height="wrap_content"ohos:text="Play Audio"/></DirectionalLayout>
III. 实现音频和视频播放功能

编写 MainAbilitySlice.java:

在 src/main/java/com/example/media/slice 目录下,创建一个 MainAbilitySlice.java 文件,实现音频和视频播放功能。

package com.example.media.slice;import ohos.aafwk.ability.AbilitySlice;import ohos.aafwk.content.Intent;import ohos.agp.components.Button;import ohos.agp.components.Video;import ohos.agp.components.Component;import ohos.media.audio.AudioPlayer;import ohos.media.audio.AudioManager;import ohos.media.audio.AudioStreamType;import ohos.media.audio.AudioSourceType;import ohos.media.audio.AudioFormat;import ohos.media.audio.AudioAttributes;import ohos.media.audio.AudioAttributes.Builder;import ohos.media.audio.AudioTrack;import ohos.media.audio.AudioStream;import ohos.media.audio.AudioTrackCallback;import ohos.media.audio.AudioData;import ohos.media.audio.AudioDataCallback;import ohos.media.audio.AudioManager;import ohos.media.audio.AudioStream;import ohos.media.audio.AudioTrack;import ohos.media.audio.AudioTrackCallback;import ohos.media.audio.AudioTrackCallback;import ohos.media.audio.AudioFormat;import ohos.media.audio.AudioData;import ohos.media.audio.AudioStream;import ohos.media.audio.AudioTrack;import ohos.media.audio.AudioTrackCallback;import ohos.media.audio.AudioTrackCallback;import java.io.IOException;import java.io.InputStream;import java.io.File;import java.io.FileInputStream;//有的写成public class MyAbility extends Ability也是可行的​public class MainAbilitySlice extends AbilitySlice {private Video videoPlayer;private Button buttonPlayVideo;private Button buttonPlayAudio;private AudioPlayer audioPlayer;@Overridepublic void onStart(Intent intent) {//这两步关键,鸿蒙无法直接展示xml布局文件,需要通过父类Ability来加载xml布局文件super.onStart(intent);super.setUIContent(ResourceTable.Layout_ability_main);​videoPlayer = (Video) findComponentById(ResourceTable.Id_video_player);buttonPlayVideo = (Button) findComponentById(ResourceTable.Id_button_play_video);buttonPlayAudio = (Button) findComponentById(ResourceTable.Id_button_play_audio);​buttonPlayVideo.setClickedListener(component -> playVideo());buttonPlayAudio.setClickedListener(component -> playAudio());}private void playVideo() {String videoPath = "path_to_video.mp4";  // Update with actual video pathvideoPlayer.setVideoPath(videoPath);videoPlayer.start();}private void playAudio() {String audioPath = "path_to_audio.mp3";  // Update with actual audio pathaudioPlayer = new AudioPlayer();audioPlayer.setAudioPath(audioPath);audioPlayer.setStreamType(AudioStreamType.MUSIC);audioPlayer.prepare();audioPlayer.start();}@Overridepublic void onStop() {super.onStop();if (audioPlayer != null) {audioPlayer.stop();audioPlayer.release();}}}

代码详细解释

IV. 音频播放实现

初始化 AudioPlayer:

在 playAudio() 方法中,我们首先创建一个 AudioPlayer 实例,设置音频文件路径,指定音频流类型为 MUSIC,并准备和开始播放音频。

 private void playAudio() {String audioPath = "path_to_audio.mp3";  // Update with actual audio pathaudioPlayer = new AudioPlayer();audioPlayer.setAudioPath(audioPath);audioPlayer.setStreamType(AudioStreamType.MUSIC);audioPlayer.prepare();audioPlayer.start();}

资源管理:

在 onStop() 方法中,我们停止并释放 AudioPlayer 实例,确保系统资源被正确释放。

 @Overridepublic void onStop() {super.onStop();if (audioPlayer != null) {audioPlayer.stop();audioPlayer.release();}}
V. 视频播放实现

初始化 Video 组件:

在 playVideo() 方法中,我们设置视频路径,并调用 start() 方法开始播放视频。

 private void playVideo() {String videoPath = "path_to_video.mp4";  // Update with actual video pathvideoPlayer.setVideoPath(videoPath);videoPlayer.start();}

更新布局:

在布局文件中定义 Video 组件用于展示视频内容,确保视频播放界面能够正确显示。

 <Videoohos:id="$+id/video_player"ohos:width="match_parent"ohos:height="200vp"ohos:layout_marginBottom="16vp"ohos:scale_type="centerCrop"/>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com