• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *  http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import media from '@ohos.multimedia.media';
17import type resourceManager from '@ohos.resourceManager';
18import emitter from '@ohos.events.emitter';
19import Logger from '../utils/Logger';
20
21const CASE_ZERO = 0;
22const CASE_ONE = 1;
23const CASE_TWO = 2;
24const CASE_THREE = 3;
25
26export default class AvPlayManage {
27  private tag: string = 'AVPlayManage';
28  private flag: boolean;
29  private avPlayer: media.AVPlayer;
30  private surfaceID: string;
31  private mgr: resourceManager.ResourceManager;
32  private currentTime: number; // 视频当前时间
33  private durationTime: number; // 视频总长
34  private speedSelect: number; // 倍速选择
35  private fileDescriptor: resourceManager.RawFileDescriptor;
36  private videoSrc: string;
37  private fileSrc: string;
38  /**
39   * 初始化视频
40   */
41  async initPlayer(surfaceId: string, callback: (avPlayer: media.AVPlayer) => void): Promise<void> {
42    Logger.info(this.tag, 'initPlayer==initCamera surfaceId== ${surfaceId}');
43    this.surfaceID = surfaceId;
44    Logger.info(this.tag, 'initPlayer==this.surfaceID surfaceId== ${this.surfaceID}');
45    try {
46      Logger.info(this.tag, 'initPlayer videoPlay avPlayerDemo');
47      // 创建avPlayer实例对象
48      this.avPlayer = await media.createAVPlayer();
49      // 创建状态机变化回调函数
50      await this.setAVPlayerCallback(callback);
51      Logger.info(this.tag, 'initPlayer videoPlay setAVPlayerCallback');
52      this.mgr = globalThis.context.resourceManager;
53      Logger.info(this.tag, 'initPlayer videoPlay this.mgr');
54      this.fileDescriptor = await this.mgr.getRawFd('test1.mp4');
55      Logger.info(this.tag, 'initPlayer videoPlay fileDescriptor = ${JSON.stringify(this.fileDescriptor)}');
56      this.avPlayer.fdSrc = this.fileDescriptor;
57    } catch (e) {
58      Logger.error(this.tag, 'initPlayer initPlayer err:${e}');
59    }
60  }
61
62  // 注册avplayer回调函数
63  async setAVPlayerCallback(callback: (avPlayer: media.AVPlayer) => void, videoSrc?: string): Promise<void> {
64    // seek操作结果回调函数
65    this.avPlayer.on('seekDone', (seekDoneTime) => {
66      Logger.info(this.tag, 'setAVPlayerCallback AVPlayer seek succeeded, seek time is ${seekDoneTime}');
67    });
68    // error回调监听函数,当avPlayer在操作过程中出现错误时调用reset接口触发重置流程
69    this.avPlayer.on('error', (err) => {
70      Logger.error(this.tag, 'setAVPlayerCallback Invoke avPlayer failed, code is ${err.code}, message is ${err.message}');
71      this.avPlayer.reset();
72    });
73    // 状态机变化回调函数
74    this.avPlayer.on('stateChange', async (state, reason) => {
75      switch (state) {
76        case 'idle': // 成功调用reset接口后触发该状态机上报
77          this.avPlayer.release();
78          this.avPlayerChoose(callback);
79          Logger.info(this.tag, 'setAVPlayerCallback AVPlayer state idle called.');
80          break;
81        case 'initialized': // avplayer 设置播放源后触发该状态上报
82          Logger.info(this.tag, 'setAVPlayerCallback AVPlayerstate initialized called.');
83          this.avPlayer.surfaceId = this.surfaceID; // 设置显示画面,当播放的资源为纯音频时无需设置
84          Logger.info(this.tag, 'setAVPlayerCallback this.avPlayer.surfaceId = ${this.avPlayer.surfaceId}');
85          this.avPlayer.prepare();
86          break;
87        case 'prepared': // prepare调用成功后上报该状态机
88          Logger.info(this.tag, 'setAVPlayerCallback AVPlayer state prepared called.');
89          this.durationTime = this.avPlayer.duration;
90          this.currentTime = this.avPlayer.currentTime;
91          this.avPlayer.play(); // 调用播放接口开始播放
92          Logger.info(this.tag, 'setAVPlayerCallback this.speedSelect = ${this.speedSelect}');
93          switch (this.speedSelect) {
94            case CASE_ZERO:
95              this.videoSpeedOne();
96              break;
97            case CASE_ONE:
98              this.videoSpeedOnePointTwentyFive();
99              break;
100            case CASE_TWO:
101              this.videoSpeedOnePointSeventyFive();
102              break;
103            case CASE_THREE:
104              this.videoSpeedTwo();
105              break;
106          }
107          callback(this.avPlayer);
108          break;
109        case 'playing': // play成功调用后触发该状态机上报
110          Logger.info(this.tag, 'setAVPlayerCallback AVPlayer state playing called.');
111          let eventDataTrue = {
112            data: {
113              'flag': true
114            }
115          };
116          let innerEventTrue = {
117            eventId: 2,
118            priority: emitter.EventPriority.HIGH
119          };
120          emitter.emit(innerEventTrue, eventDataTrue);
121          break;
122        case 'completed': // 播放结束后触发该状态机上报
123          Logger.info(this.tag, 'setAVPlayerCallback AVPlayer state completed called.');
124          let eventDataFalse = {
125            data: {
126              'flag': false
127            }
128          };
129          let innerEvent = {
130            eventId: 1,
131            priority: emitter.EventPriority.HIGH
132          };
133          emitter.emit(innerEvent, eventDataFalse);
134          break;
135        default:
136          Logger.info(this.tag, 'setAVPlayerCallback AVPlayer state unknown called.');
137          break;
138      }
139    });
140    // 时间上报监听函数
141    this.avPlayer.on('timeUpdate', (time: number) => {
142      this.currentTime = time;
143      Logger.info(this.tag, 'setAVPlayerCallback timeUpdate success,and new time is = ${this.currentTime}');
144    });
145  }
146
147  /**
148   * 获取总时间
149   */
150  getDurationTime(): number {
151    return this.durationTime;
152  }
153
154  /**
155   * 获取当前时间
156   */
157  getCurrentTime(): number {
158    return this.currentTime;
159  }
160
161  /**
162   * 视频播放
163   */
164  videoPlay(): void {
165    if (this.avPlayer) {
166      try {
167        this.avPlayer.play();
168      } catch (e) {
169        Logger.error(this.tag, 'videoPlay = ${JSON.stringify(e)}');
170      }
171    }
172  }
173
174  /**
175   * 视频暂停
176   */
177  videoPause(): void {
178    if (this.avPlayer) {
179      try {
180        this.avPlayer.pause();
181        Logger.info(this.tag, 'videoPause==');
182      } catch (e) {
183        Logger.info(this.tag, 'videoPause== ${JSON.stringify(e)}');
184      }
185    }
186  }
187
188  /**
189   * 调节1.0倍速
190   */
191  videoSpeedOne(): void {
192    if (this.avPlayer) {
193      try {
194        this.avPlayer.setSpeed(media.PlaybackSpeed.SPEED_FORWARD_1_00_X);
195        Logger.info(this.tag, 'videoSpeed_1_00');
196      } catch (e) {
197        Logger.info(this.tag, 'videoSpeed_1_00== ${JSON.stringify(e)}');
198      }
199    }
200  }
201
202  /**
203   * 调节1.25倍速
204   */
205  videoSpeedOnePointTwentyFive(): void {
206    if (this.avPlayer) {
207      try {
208        this.avPlayer.setSpeed(media.PlaybackSpeed.SPEED_FORWARD_1_25_X);
209        Logger.info(this.tag, 'videoSpeed_1_25');
210      } catch (e) {
211        Logger.info(this.tag, 'videoSpeed_1_25== ${JSON.stringify(e)}');
212      }
213    }
214  }
215
216  /**
217   * 调节1.75倍速
218   */
219  videoSpeedOnePointSeventyFive(): void {
220    if (this.avPlayer) {
221      try {
222        this.avPlayer.setSpeed(media.PlaybackSpeed.SPEED_FORWARD_1_75_X);
223        Logger.info(this.tag, 'videoSpeed_1_75');
224      } catch (e) {
225        Logger.info(this.tag, 'videoSpeed_1_75==' + JSON.stringify(e));
226      }
227    }
228  }
229
230  /**
231   * 调节2.0倍速
232   */
233  videoSpeedTwo(): void {
234    if (this.avPlayer) {
235      try {
236        this.avPlayer.setSpeed(media.PlaybackSpeed.SPEED_FORWARD_2_00_X);
237        Logger.info(this.tag, 'videoSpeed_2_0');
238      } catch (e) {
239        Logger.info(this.tag, 'videoSpeed_2_0== ${JSON.stringify(e)}');
240      }
241    }
242  }
243
244  /**
245   * 视频跳转
246   */
247  videoSeek(seekTime: number): void {
248    if (this.avPlayer) {
249      try {
250        this.avPlayer.seek(seekTime, media.SeekMode.SEEK_PREV_SYNC);
251        Logger.info(this.tag, 'videoSeek== ${seekTime}');
252      } catch (e) {
253        Logger.info(this.tag, 'videoSeek== ${JSON.stringify(e)}');
254      }
255    }
256  }
257
258  /**
259   * 视频重置
260   */
261  async videoReset(): Promise<void> {
262    this.avPlayer.reset();
263  }
264
265  /**
266   * 释放视频资源
267   */
268  async videoRelease(): Promise<void> {
269    this.avPlayer.release((err) => {
270      if (err == null) {
271        Logger.info(this.tag, 'videoRelease release success');
272      } else {
273        Logger.error(this.tag, 'videoRelease release filed,error message is = ${err.message}');
274      }
275    });
276  }
277
278  /**
279   * 视频切换,前台调用
280   */
281  async videoChoose(videoSrc: string, speedSelect: number, callback: (avPlayer: media.AVPlayer) => void): Promise<void> {
282    try {
283      this.flag = false;
284      this.videoSrc = videoSrc;
285      this.speedSelect = speedSelect;
286      Logger.info(this.tag, 'videoChoose this.videoSrc = ${this.videoSrc}');
287      this.videoReset();
288    } catch (e) {
289      Logger.info(this.tag, 'videoChoose== ${JSON.stringify(e)}');
290    }
291  }
292
293  /**
294   * 视频切换,换视频资源
295   */
296  async avPlayerChoose(callback: (avPlayer: media.AVPlayer) => void): Promise<void> {
297    try {
298      Logger.info(this.tag, 'avPlayerChoose avPlayerDemo');
299      // 创建avPlayer实例对象
300      this.avPlayer = await media.createAVPlayer();
301      // 创建状态机变化回调函数
302      this.fileDescriptor = null;
303      Logger.info(this.tag, 'avPlayerChoose this.fileDescriptor = ${this.fileDescriptor}');
304      await this.setAVPlayerCallback(callback);
305      Logger.info(this.tag, 'avPlayerChoose setAVPlayerCallback');
306      if (this.videoSrc === 'network.mp4') {
307        this.fileSrc = 'https:\/\/vd3.bdstatic.com\/mda-pdc2kmwtd2vxhiy4\/cae_h264\/1681502407203843413\/mda-pdc2kmwtd2vxhiy4.mp4';
308      } else {
309        this.fileSrc = this.videoSrc;
310      }
311      let regex = /^(http|https)/i;
312      let bool = regex.test(this.fileSrc);
313      if (bool) {
314        Logger.info(this.tag, 'avPlayerChoose avPlayerChoose fileDescriptor = ${JSON.stringify(this.fileDescriptor)}');
315        this.avPlayer.url = this.fileSrc;
316      } else {
317        this.fileDescriptor = await this.mgr.getRawFd(this.fileSrc);
318        Logger.info(this.tag, 'avPlayerChoose avPlayerChoose fileDescriptor = ${JSON.stringify(this.fileDescriptor)}');
319        this.avPlayer.fdSrc = this.fileDescriptor;
320      }
321    } catch (e) {
322      Logger.info(this.tag, 'avPlayerChoose trycatch avPlayerChoose');
323      this.videoReset();
324    }
325  }
326}