@cc-component/cc-video 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cc-ex-component.md +12 -0
- package/assets/video/Interface.ts +26 -0
- package/assets/video/Interface.ts.meta +9 -0
- package/assets/video/VideoComponent.prefab +614 -0
- package/assets/video/VideoComponent.prefab.meta +13 -0
- package/assets/video/base/IVideo.ts +73 -0
- package/assets/video/base/IVideo.ts.meta +9 -0
- package/assets/video/base/VideoComponent.ts +33 -0
- package/assets/video/base/VideoComponent.ts.meta +9 -0
- package/assets/video/base/VideoManager.ts +399 -0
- package/assets/video/base/VideoManager.ts.meta +9 -0
- package/assets/video/base/VideoModule.ts +137 -0
- package/assets/video/base/VideoModule.ts.meta +9 -0
- package/assets/video/base/VideoPlayTT.ts +338 -0
- package/assets/video/base/VideoPlayTT.ts.meta +9 -0
- package/assets/video/base/VideoPlayWX.ts +274 -0
- package/assets/video/base/VideoPlayWX.ts.meta +9 -0
- package/assets/video/base/VideoPlayWeb.ts +228 -0
- package/assets/video/base/VideoPlayWeb.ts.meta +9 -0
- package/assets/video/base/list.meta +9 -0
- package/assets/video/base.meta +9 -0
- package/assets/video.meta +9 -0
- package/assets.meta +9 -0
- package/index.ts +3 -0
- package/index.ts.meta +9 -0
- package/package.json +19 -0
- package/package.json.meta +11 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Component, Node } from "cc";
|
|
2
|
+
|
|
3
|
+
export interface InitParam {
|
|
4
|
+
node: Node,
|
|
5
|
+
cover: Node,
|
|
6
|
+
bg: Node,
|
|
7
|
+
bundle: string,
|
|
8
|
+
dir: string,
|
|
9
|
+
cover_dir: string,
|
|
10
|
+
remote_url: string,
|
|
11
|
+
proCall?: (pro: number) => void
|
|
12
|
+
}
|
|
13
|
+
export interface IVideoData {
|
|
14
|
+
/**视频文件名称 */
|
|
15
|
+
name: string,
|
|
16
|
+
/**开始时间*/
|
|
17
|
+
start_time?: number,
|
|
18
|
+
/**结束时间 */
|
|
19
|
+
end_time?: number
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface IVideoParam {
|
|
23
|
+
/**本次播放或者加载,是否指定目标大小*/
|
|
24
|
+
isTargetSize?: boolean,
|
|
25
|
+
/**是否是 时间段 视频,备注:多个小视频合成一个大视频 */
|
|
26
|
+
isPlayTime?: boolean,
|
|
27
|
+
/**循环播放 */
|
|
28
|
+
isLoop?: boolean,
|
|
29
|
+
/**封面图片 */
|
|
30
|
+
coverImage?: string,
|
|
31
|
+
/**全屏并且-保持原比例 */
|
|
32
|
+
isVideoFit?: boolean,
|
|
33
|
+
/**视频封面 */
|
|
34
|
+
onRead?: Function,
|
|
35
|
+
/**播放完成 */
|
|
36
|
+
onFinish?: Function,
|
|
37
|
+
/**可不设置
|
|
38
|
+
* 是本地视频还是远程,
|
|
39
|
+
* 小游戏会设置为:远程视频,
|
|
40
|
+
* 安卓和ios原生端会可不设置,根据url 判断是远程还是本地视频 */
|
|
41
|
+
isLocal?: boolean,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
// export interface IVideoParam {
|
|
46
|
+
// isPlayTime?: boolean,
|
|
47
|
+
// isLoop?: boolean,
|
|
48
|
+
// finish?: Function,
|
|
49
|
+
|
|
50
|
+
// }
|
|
51
|
+
|
|
52
|
+
export class BaseVideo extends Component {
|
|
53
|
+
initVideo(initParam: { bundle: string, dir: string }) { }
|
|
54
|
+
loadVideo(name: string, param?: IVideoParam) { }
|
|
55
|
+
play(isloop?: boolean) { }
|
|
56
|
+
async pause() { }
|
|
57
|
+
stop() { }
|
|
58
|
+
resume() { }
|
|
59
|
+
seek(time: number) { }
|
|
60
|
+
destroyVideo() { }
|
|
61
|
+
setSize(param: { x: number, y: number, width: number, height: number }) { }
|
|
62
|
+
autoSize() { }
|
|
63
|
+
onTimeUpdate: (data: { position: number, duration: number }) => void;
|
|
64
|
+
onError: Function
|
|
65
|
+
onVideoEnd: Function
|
|
66
|
+
onRead: Function
|
|
67
|
+
getisPause(): boolean {
|
|
68
|
+
return false
|
|
69
|
+
}
|
|
70
|
+
// getDuration(): number;
|
|
71
|
+
// isPlaying: boolean;
|
|
72
|
+
// isLocal:boolean;
|
|
73
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { _decorator, Component, Node } from 'cc';
|
|
2
|
+
import { VideoModule } from './VideoModule';
|
|
3
|
+
import { Camera } from 'cc';
|
|
4
|
+
import { director } from 'cc';
|
|
5
|
+
import { Color } from 'cc';
|
|
6
|
+
const { ccclass, property } = _decorator;
|
|
7
|
+
@ccclass('VideoComponent')
|
|
8
|
+
export class VideoComponent extends Component {
|
|
9
|
+
@property({ displayName: '备注:' })
|
|
10
|
+
des: string = '项目设置-宏配置-ENABLE_TRANSPARENT_CANVAS,开启透明画布'
|
|
11
|
+
@property({ displayName: '视频bundle' })
|
|
12
|
+
bundle_name: string = 'resources'
|
|
13
|
+
@property({ displayName: '封面目录' })
|
|
14
|
+
video_dir: string = 'video_dir'
|
|
15
|
+
@property({ displayName: '封面目录' })
|
|
16
|
+
cover_dir: string = 'cover_dir'
|
|
17
|
+
@property({ displayName: '远程地址根目录', tooltip: '视频远程地址全路径示例: https://hcy-cdn-domestic.wyx.cn/online/comeback/xxx.mp4' })
|
|
18
|
+
remote_url: string = 'https://hcy-cdn-domestic.wyx.cn/online/comeback/video/'
|
|
19
|
+
protected onLoad(): void {
|
|
20
|
+
//const camera = director.getScene().getComponentsInChildren(Camera)[0]
|
|
21
|
+
// camera.clearColor = new Color(0, 0, 0, 0)
|
|
22
|
+
VideoModule.initVideo({
|
|
23
|
+
node: this.node.getChildByPath('video'),
|
|
24
|
+
cover: this.node.getChildByName('cover'),
|
|
25
|
+
bg: this.node.getChildByName('bg'),
|
|
26
|
+
bundle: this.bundle_name,
|
|
27
|
+
dir: this.video_dir,
|
|
28
|
+
cover_dir: this.cover_dir,
|
|
29
|
+
remote_url: this.remote_url
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
import { VideoPlayer, Node, sys, Sprite, UITransform, Size, view, assetManager, SpriteFrame, AssetManager, Asset } from 'cc';
|
|
2
|
+
import { _decorator } from 'cc';
|
|
3
|
+
import { BaseVideo, InitParam, IVideoData, IVideoParam } from './IVideo';
|
|
4
|
+
import { VideoPlayWeb } from './VideoPlayWeb';
|
|
5
|
+
import { VideoPlayWX } from './VideoPlayWX';
|
|
6
|
+
import { WECHAT } from 'cc/env';
|
|
7
|
+
import { VideoPlayTT } from './VideoPlayTT';
|
|
8
|
+
const { ccclass, property } = _decorator;
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
export class VideoManager {
|
|
13
|
+
Debug: boolean = false;
|
|
14
|
+
static _instance: VideoManager = null!;
|
|
15
|
+
public static get instance(): VideoManager {
|
|
16
|
+
if (!VideoManager._instance) {
|
|
17
|
+
VideoManager._instance = new VideoManager();
|
|
18
|
+
}
|
|
19
|
+
return VideoManager._instance;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
isPlaying: boolean;
|
|
23
|
+
isloop: boolean;
|
|
24
|
+
baseVideo: BaseVideo;
|
|
25
|
+
// 添加一个标志位用于控制是否停止播放
|
|
26
|
+
private stopRequested: boolean = false;
|
|
27
|
+
|
|
28
|
+
/** 封面图 */
|
|
29
|
+
cover: Sprite;
|
|
30
|
+
isError: boolean = false;
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
currentIndex = 0;
|
|
34
|
+
currentList: IVideoData[] = [];
|
|
35
|
+
node: Node;
|
|
36
|
+
taskId = 'mainVideoList';
|
|
37
|
+
param: IVideoParam = {
|
|
38
|
+
isLoop: false,
|
|
39
|
+
isLocal: false,
|
|
40
|
+
isPlayTime: false,
|
|
41
|
+
isTargetSize: false
|
|
42
|
+
};
|
|
43
|
+
paramPlay: IVideoParam = {
|
|
44
|
+
isLoop: false,
|
|
45
|
+
isPlayTime: true,
|
|
46
|
+
isTargetSize: false
|
|
47
|
+
};
|
|
48
|
+
paramInit: InitParam;
|
|
49
|
+
cur_name = "";
|
|
50
|
+
get isLoop() {
|
|
51
|
+
if (this.paramPlay.isLoop === undefined || this.paramPlay.isLoop === null) {
|
|
52
|
+
return true
|
|
53
|
+
}
|
|
54
|
+
return this.paramPlay.isLoop
|
|
55
|
+
}
|
|
56
|
+
get isPlayTime() {
|
|
57
|
+
if (this.param.isPlayTime === undefined || this.param.isPlayTime === null) {
|
|
58
|
+
return false
|
|
59
|
+
}
|
|
60
|
+
return this.param.isPlayTime
|
|
61
|
+
}
|
|
62
|
+
get isMinGame() {
|
|
63
|
+
if (WECHAT) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
remote_url = ""
|
|
70
|
+
initVideo(param: InitParam) {
|
|
71
|
+
this.paramInit = param;
|
|
72
|
+
this.node = param.node;
|
|
73
|
+
this.cover = param.cover.getComponent(Sprite);
|
|
74
|
+
this.cover.node.active = false;
|
|
75
|
+
this.node.addChild(this.cover.node);
|
|
76
|
+
switch (sys.platform) {
|
|
77
|
+
case sys.Platform.ANDROID:
|
|
78
|
+
this.baseVideo = this.node.addComponent(VideoPlayWeb);
|
|
79
|
+
break;
|
|
80
|
+
case sys.Platform.WECHAT_GAME:
|
|
81
|
+
this.baseVideo = this.node.addComponent(VideoPlayWX);
|
|
82
|
+
break;
|
|
83
|
+
case sys.Platform.BYTEDANCE_MINI_GAME:
|
|
84
|
+
this.baseVideo = this.node.addComponent(VideoPlayTT);
|
|
85
|
+
break;
|
|
86
|
+
default:
|
|
87
|
+
this.baseVideo = this.node.addComponent(VideoPlayWeb);
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
this.baseVideo.initVideo({ bundle: this.paramInit.bundle, dir: param.dir });
|
|
91
|
+
this.baseVideo.onTimeUpdate = async (data: { position: number, duration: number }) => {
|
|
92
|
+
if (this.currentList.length <= 0) {
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
const currentName = this.currentList[this.currentIndex]
|
|
96
|
+
//console.log("时间:", !this.baseVideo.getisPause(),data.position , currentName.end);
|
|
97
|
+
if (this.isLoop) {
|
|
98
|
+
if (data.position >= currentName.end_time && !this.baseVideo.getisPause()) {
|
|
99
|
+
if (VideoManager.instance.Debug)
|
|
100
|
+
console.log("播放结束:", currentName, !this.baseVideo.getisPause);
|
|
101
|
+
await this.pause();
|
|
102
|
+
this.currentIndex++;
|
|
103
|
+
if (this.currentIndex === this.currentList.length) {
|
|
104
|
+
this.currentIndex = 0;
|
|
105
|
+
}
|
|
106
|
+
this.playVideoTime(this.currentList[this.currentIndex])
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
} else {
|
|
110
|
+
if (data.position >= currentName.end_time && !this.baseVideo.getisPause()) {
|
|
111
|
+
if (VideoManager.instance.Debug)
|
|
112
|
+
console.log("播放结束:", currentName, !this.baseVideo.getisPause);
|
|
113
|
+
await this.pause();
|
|
114
|
+
this.paramPlay?.onFinish?.()
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
};
|
|
119
|
+
this.baseVideo.onError = (err) => {
|
|
120
|
+
this.isError = true;
|
|
121
|
+
console.error("视频报错了", err)
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
this.baseVideo.onVideoEnd = () => {
|
|
125
|
+
if (VideoManager.instance.Debug)
|
|
126
|
+
console.warn("视频播放完成")
|
|
127
|
+
const taskId = 'mainVideoList';
|
|
128
|
+
if (this.playTasks.has(taskId)) {
|
|
129
|
+
const task = this.playTasks.get(taskId);
|
|
130
|
+
if (task && task.finishPlayResolve) {
|
|
131
|
+
task.finishPlayResolve();
|
|
132
|
+
// 调用后清空引用
|
|
133
|
+
// task.finishPlayResolve = null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (this.paramPlay?.onFinish) {
|
|
137
|
+
this.paramPlay.onFinish();
|
|
138
|
+
if (this.paramPlay.isLoop)
|
|
139
|
+
this.paramPlay.onFinish = undefined;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
this.baseVideo.onRead = () => {
|
|
143
|
+
if (VideoManager.instance.Debug)
|
|
144
|
+
console.log("视频准备好了")
|
|
145
|
+
this.cover.node.active = false
|
|
146
|
+
this.seek(0)
|
|
147
|
+
if (this.param.isLocal) {
|
|
148
|
+
//this.play()
|
|
149
|
+
//console.log("开始播放")
|
|
150
|
+
this.param?.onRead?.()
|
|
151
|
+
}
|
|
152
|
+
else if (this.param.isPlayTime) {
|
|
153
|
+
this.pause()
|
|
154
|
+
this.param?.onRead?.()
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
this.pause()
|
|
158
|
+
this.param?.onRead?.()
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
this.autoSize()
|
|
163
|
+
|
|
164
|
+
}
|
|
165
|
+
// 在类中添加属性(您已经添加了)
|
|
166
|
+
coount = 0
|
|
167
|
+
// 修改 playTasks 的类型定义,增加 finishPlayResolve 字段
|
|
168
|
+
private playTasks: Map<string, { count: number, stop: () => void, finishPlayResolve: (() => void) | null }> = new Map();
|
|
169
|
+
|
|
170
|
+
// 在 playVideoList 方法中更新存储逻辑
|
|
171
|
+
loadVideo(name: string, param: IVideoParam): void {
|
|
172
|
+
name = param.isLocal ? name : `${this.remote_url}${name}.mp4`
|
|
173
|
+
if (VideoManager.instance.Debug)
|
|
174
|
+
console.log("加载视频:", name);
|
|
175
|
+
this.param = param;
|
|
176
|
+
this.cover.spriteFrame = assetManager.getBundle(this.paramInit.bundle)?.get(`${this.paramInit.cover_dir}/${param.coverImage}/spriteFrame`)
|
|
177
|
+
this.cover.node.active = this.cur_name === name ? false : true;
|
|
178
|
+
|
|
179
|
+
this.baseVideo.loadVideo(name, param)
|
|
180
|
+
this.cur_name = name;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private play(): void {
|
|
184
|
+
this.baseVideo.play()
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
setSize(param: { x: number, y: number, width: number, height: number }) {
|
|
188
|
+
this.baseVideo.setSize(param)
|
|
189
|
+
}
|
|
190
|
+
// 节点位置适配
|
|
191
|
+
autoSize() {
|
|
192
|
+
this.baseVideo.autoSize()
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
async pause() {
|
|
197
|
+
await this.baseVideo.pause()
|
|
198
|
+
}
|
|
199
|
+
stop(): void {
|
|
200
|
+
}
|
|
201
|
+
resume(): void {
|
|
202
|
+
}
|
|
203
|
+
seek(time: number): void {
|
|
204
|
+
this.baseVideo.seek(time)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**播放单个视频 */
|
|
208
|
+
playVideo(param?: IVideoParam): void {
|
|
209
|
+
this.paramPlay = param
|
|
210
|
+
this.baseVideo.play(param?.isLoop)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
playVideoOne(name: string, param: IVideoParam) {
|
|
214
|
+
// if (VideoManager.instance.Debug)
|
|
215
|
+
// console.log('加载视频', name)
|
|
216
|
+
const isloop = false
|
|
217
|
+
const onRead = param.onRead
|
|
218
|
+
param.onRead = () => {
|
|
219
|
+
console.warn('当前播放', name)
|
|
220
|
+
onRead?.()
|
|
221
|
+
this.playVideo(param)
|
|
222
|
+
}
|
|
223
|
+
this.loadVideo(name, param)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private playVideoTime(name: IVideoData): void {
|
|
227
|
+
if (VideoManager.instance.Debug)
|
|
228
|
+
console.warn('当前播放', name.start_time, name.end_time)
|
|
229
|
+
|
|
230
|
+
this.baseVideo.seek(name.start_time)
|
|
231
|
+
this.baseVideo.play()
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
//#region 新方案
|
|
235
|
+
async playVideoList(list: IVideoData[], param: IVideoParam) {
|
|
236
|
+
this.paramPlay = param
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
// 如果存在正在播放的任务,先停止它
|
|
240
|
+
const taskId = this.taskId
|
|
241
|
+
this.stopTask(taskId)
|
|
242
|
+
//新任务延迟1帧
|
|
243
|
+
setTimeout(async () => {
|
|
244
|
+
this.currentList = list;
|
|
245
|
+
this.currentIndex = 0
|
|
246
|
+
if (VideoManager.instance.Debug)
|
|
247
|
+
console.log("当前播放列表", JSON.stringify(list))
|
|
248
|
+
this.coount++;
|
|
249
|
+
// 重置状态
|
|
250
|
+
this.stopRequested = false;
|
|
251
|
+
this.isError = false;
|
|
252
|
+
// 创建停止函数
|
|
253
|
+
let isStopped = false;
|
|
254
|
+
const stopFunction = () => {
|
|
255
|
+
isStopped = true;
|
|
256
|
+
this.stopRequested = true;
|
|
257
|
+
if (this.baseVideo) {
|
|
258
|
+
//this.baseVideo.pause();
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
if (VideoManager.instance.Debug)
|
|
262
|
+
console.log("开始任务", this.coount)
|
|
263
|
+
// 将停止函数和 finishPlayResolve 存储到Map中
|
|
264
|
+
this.playTasks.set(taskId, { count: this.coount, stop: stopFunction, finishPlayResolve: null });
|
|
265
|
+
const oldTask = this.playTasks.get(taskId);
|
|
266
|
+
// 调用原始的播放逻辑
|
|
267
|
+
await this._playVideoList(list, param, taskId);
|
|
268
|
+
// 清理任务
|
|
269
|
+
if (VideoManager.instance.Debug)
|
|
270
|
+
console.log('任务已结束', oldTask?.count);
|
|
271
|
+
if (!param.isLoop)
|
|
272
|
+
param.onFinish?.()
|
|
273
|
+
//this.playTasks.delete(taskId);
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
stopTask(taskId: string) {
|
|
278
|
+
if (this.playTasks.has(taskId)) {
|
|
279
|
+
let oldTask: any = this.playTasks.get(taskId);
|
|
280
|
+
if (oldTask) {
|
|
281
|
+
// 调用之前存储的 finishPlayResolve 来中断等待
|
|
282
|
+
if (oldTask.finishPlayResolve) {
|
|
283
|
+
oldTask.finishPlayResolve();
|
|
284
|
+
}
|
|
285
|
+
oldTask.stop();
|
|
286
|
+
}
|
|
287
|
+
this.playTasks.delete(taskId);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
}
|
|
291
|
+
// 在 _playVideoList 方法中更新 finishPlayResolve 的存储
|
|
292
|
+
async _playVideoList(list: IVideoData[], param: IVideoParam, taskId: string) {
|
|
293
|
+
// this.cover.node.active = true
|
|
294
|
+
for (let index = 0; index < list.length; index++) {
|
|
295
|
+
// 检查是否需要停止
|
|
296
|
+
if (this.stopRequested) {
|
|
297
|
+
if (VideoManager.instance.Debug)
|
|
298
|
+
console.log("播放被停止");
|
|
299
|
+
break;
|
|
300
|
+
}
|
|
301
|
+
if (this.isError) { break; }
|
|
302
|
+
const name = list[index];
|
|
303
|
+
if (this.isPlayTime) {
|
|
304
|
+
this.playVideoTime(name)
|
|
305
|
+
} else {
|
|
306
|
+
this.playVideoOne(name.name, param)
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// 更新 playTasks 中的 finishPlayResolve
|
|
310
|
+
await new Promise<void>((resolve, reject) => {
|
|
311
|
+
// 更新Map中的 finishPlayResolve 引用
|
|
312
|
+
if (this.playTasks.has(taskId)) {
|
|
313
|
+
const task = this.playTasks.get(taskId);
|
|
314
|
+
if (task) {
|
|
315
|
+
task.finishPlayResolve = resolve;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
if (this.isError) { break; }
|
|
321
|
+
if (VideoManager.instance.Debug)
|
|
322
|
+
console.warn('停止', this.stopRequested)
|
|
323
|
+
if (this.stopRequested) {
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (VideoManager.instance.Debug)
|
|
328
|
+
console.log('播放结束')
|
|
329
|
+
if (param.isLoop) {
|
|
330
|
+
// 同样检查停止请求
|
|
331
|
+
if (!this.stopRequested) {
|
|
332
|
+
this._playVideoList(list, param, taskId)
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
// 增加停止播放列表的方法
|
|
339
|
+
public stopVideoList() {
|
|
340
|
+
this.stopRequested = true;
|
|
341
|
+
this.stopTask(this.taskId)
|
|
342
|
+
this.baseVideo.destroyVideo()
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
async loadBundle(bundleName) {
|
|
346
|
+
let bundle = assetManager.getBundle(bundleName);
|
|
347
|
+
if (!bundle) {
|
|
348
|
+
bundle = await new Promise<AssetManager.Bundle>(resolve => {
|
|
349
|
+
assetManager.loadBundle(bundleName, (err, bundle) => {
|
|
350
|
+
if (err) {
|
|
351
|
+
|
|
352
|
+
console.error("没有bundle", bundleName, err)
|
|
353
|
+
return
|
|
354
|
+
} else {
|
|
355
|
+
resolve(bundle)
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
})
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
// 在 VideoManager 类中添加以下方法
|
|
362
|
+
/**加载视频 */
|
|
363
|
+
preLoadVideo(bundleName: string, dirs: string[], pro: (pro: number) => void) {
|
|
364
|
+
return new Promise<void>(async (resolve, reject) => {
|
|
365
|
+
let bundle = assetManager.getBundle(bundleName);
|
|
366
|
+
if (!bundle) {
|
|
367
|
+
bundle = await new Promise<AssetManager.Bundle>(resolve => {
|
|
368
|
+
assetManager.loadBundle(bundleName, (err, bundle) => {
|
|
369
|
+
if (err) {
|
|
370
|
+
reject(err);
|
|
371
|
+
} else {
|
|
372
|
+
resolve(bundle)
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
})
|
|
376
|
+
}
|
|
377
|
+
let pro_num = 0
|
|
378
|
+
|
|
379
|
+
for (let index = 0; index < dirs.length; index++) {
|
|
380
|
+
const dir = dirs[index];
|
|
381
|
+
await new Promise<void>(resolve => {
|
|
382
|
+
bundle.loadDir(dir, (fin, total) => {
|
|
383
|
+
const value = fin / total * 100;
|
|
384
|
+
pro?.(Math.floor(value));
|
|
385
|
+
}, (err, assets) => {
|
|
386
|
+
resolve()
|
|
387
|
+
})
|
|
388
|
+
})
|
|
389
|
+
// let pro_add = (index + 1) / dirs.length
|
|
390
|
+
// pro_num = pro_add * 100
|
|
391
|
+
// pro?.(index);
|
|
392
|
+
}
|
|
393
|
+
resolve()
|
|
394
|
+
})
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { _decorator, assetManager, Component, Node, randomRangeInt } from 'cc';
|
|
2
|
+
import { VideoManager } from './VideoManager';
|
|
3
|
+
import { InitParam, IVideoData, IVideoParam } from './IVideo';
|
|
4
|
+
import { BYTEDANCE, WECHAT } from 'cc/env';
|
|
5
|
+
import { sys } from 'cc';
|
|
6
|
+
import { VideoPlayTT } from './VideoPlayTT';
|
|
7
|
+
import { VideoPlayWeb } from './VideoPlayWeb';
|
|
8
|
+
import { VideoPlayWX } from './VideoPlayWX';
|
|
9
|
+
const { ccclass, property } = _decorator;
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
export class VideoModule {
|
|
13
|
+
static _instance: VideoModule = null;
|
|
14
|
+
static get instance(): VideoModule {
|
|
15
|
+
if (!this._instance) {
|
|
16
|
+
this._instance = new VideoModule();
|
|
17
|
+
}
|
|
18
|
+
return this._instance;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get isMinGame() {
|
|
22
|
+
if (WECHAT || BYTEDANCE) {
|
|
23
|
+
return true
|
|
24
|
+
}
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
/**视频地址 */
|
|
28
|
+
remote_url = "https://hcy-cdn-domestic.wyx.cn/online/comeback/";
|
|
29
|
+
static async initVideo(param: InitParam) {
|
|
30
|
+
// if (BYTEDANCE) {
|
|
31
|
+
// param.bg.active = true;
|
|
32
|
+
// this.remote_url += "video_dy/"
|
|
33
|
+
// }
|
|
34
|
+
// else if (WECHAT) {
|
|
35
|
+
// param.bg.active = false;
|
|
36
|
+
// this.remote_url += "video_dy/"
|
|
37
|
+
// }
|
|
38
|
+
// else {
|
|
39
|
+
// param.bg.active = false;
|
|
40
|
+
// this.remote_url += "video/"
|
|
41
|
+
// await VideoManager.instance.loadBundle(param.bundle)
|
|
42
|
+
// }
|
|
43
|
+
VideoManager.instance.remote_url = param.remote_url
|
|
44
|
+
VideoManager.instance.initVideo(param)
|
|
45
|
+
console.log("视频初始化完成")
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static Debug(enabled: boolean) { VideoManager.instance.Debug = enabled }
|
|
49
|
+
/**视频设置到指定大小 */
|
|
50
|
+
static SetSize(param: { x: number, y: number, width: number, height: number }) { VideoManager.instance.setSize(param) }
|
|
51
|
+
/**节点位置适配-自动适配 */
|
|
52
|
+
static AutoSize() { VideoManager.instance.autoSize() }
|
|
53
|
+
/**暂停 */
|
|
54
|
+
static async Pause() { return await VideoManager.instance.pause() }
|
|
55
|
+
/**继续 */
|
|
56
|
+
static async Resume() { return await VideoManager.instance.resume() }
|
|
57
|
+
/**停止视频 */
|
|
58
|
+
static StopVideoTask() { VideoManager.instance.stopVideoList() }
|
|
59
|
+
|
|
60
|
+
/**提前加载视频 */
|
|
61
|
+
static LoadVideo(name: string, param: IVideoParam) {
|
|
62
|
+
VideoManager.instance.stopVideoList()
|
|
63
|
+
param.isLocal = VideoModule.isLocal(name)
|
|
64
|
+
VideoManager.instance.loadVideo(name, param)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**播放单个视频 */
|
|
68
|
+
static PlayVideo(video: IVideoData, param: IVideoParam) {
|
|
69
|
+
VideoManager.instance.stopVideoList()
|
|
70
|
+
param.isLocal = VideoModule.isLocal(video.name)
|
|
71
|
+
const onRead = param.onRead
|
|
72
|
+
param.onRead = () => {
|
|
73
|
+
onRead?.()
|
|
74
|
+
VideoManager.instance.playVideo(param)
|
|
75
|
+
}
|
|
76
|
+
VideoManager.instance.loadVideo(video.name, param)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** 播放多个视频*/
|
|
80
|
+
static PlayVideoMore(video_list: IVideoData[], param: IVideoParam) {
|
|
81
|
+
const url = video_list[0].name
|
|
82
|
+
param.isLocal = VideoModule.isLocal(url)
|
|
83
|
+
if (param.isPlayTime) {
|
|
84
|
+
const onRead = param.onRead
|
|
85
|
+
param.onRead = () => {
|
|
86
|
+
onRead?.()
|
|
87
|
+
VideoManager.instance.playVideoList(video_list, param)
|
|
88
|
+
}
|
|
89
|
+
VideoManager.instance.loadVideo(url, param)
|
|
90
|
+
} else {
|
|
91
|
+
VideoManager.instance.playVideoList(video_list, param)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
static isLocal(url: string) {
|
|
96
|
+
let result = url
|
|
97
|
+
switch (sys.platform) {
|
|
98
|
+
case sys.Platform.WECHAT_GAME:
|
|
99
|
+
case sys.Platform.BYTEDANCE_MINI_GAME:
|
|
100
|
+
result = `${VideoManager.instance.paramInit.remote_url}${url}`
|
|
101
|
+
break;
|
|
102
|
+
default:
|
|
103
|
+
// result = `${VideoManager.instance.paramInit.remote_url}${url}`
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
return !result.includes("http")
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
//#region 本地视频
|
|
111
|
+
/**播放单个视频 -本地视频 */
|
|
112
|
+
// public play(url: string, param: IVideoParam) {
|
|
113
|
+
// VideoManager.instance.loadVideo(url, {
|
|
114
|
+
// isLoop: param.isLoop, isVideoFit: param.isVideoFit, isLocal: param.isLocal, isPlayTime: param.isPlayTime, coverImage: param.coverImage, onRead: () => {
|
|
115
|
+
// VideoManager.instance.playVideo({
|
|
116
|
+
// isLoop: param.isLoop,
|
|
117
|
+
// finish: param.onRead
|
|
118
|
+
// })
|
|
119
|
+
// }
|
|
120
|
+
// })
|
|
121
|
+
// }
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
// //#region 网络视频
|
|
125
|
+
// /**播放单个视频 --- */
|
|
126
|
+
// public playRemote(url: string, param: { isloop: boolean, coverImage: string, finish: Function }) {
|
|
127
|
+
// VideoManager.instance.loadVideo(url, {
|
|
128
|
+
// isLoop: param.isloop, isLocal: false, isPlayTime: false, coverImage: param.coverImage, onRead: () => {
|
|
129
|
+
// VideoManager.instance.playVideo({
|
|
130
|
+
// isLoop: param.isloop,
|
|
131
|
+
// finish: param.finish
|
|
132
|
+
// })
|
|
133
|
+
// }
|
|
134
|
+
// })
|
|
135
|
+
// }
|
|
136
|
+
}
|
|
137
|
+
window.VideoModule = VideoModule;
|