@linker-design-plus/mpegtsplayer 1.0.0 → 1.0.2

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/dist/index.mjs ADDED
@@ -0,0 +1,253 @@
1
+ import { getCurrentInstance as x, inject as z, defineComponent as P, computed as S, openBlock as D, createElementBlock as F, normalizeClass as j, normalizeStyle as A, createElementVNode as V, ref as f, watch as U, nextTick as G, onMounted as W, onUnmounted as J, createVNode as y, createTextVNode as q } from "vue";
2
+ import c from "mpegts.js";
3
+ const H = Symbol("ArcoConfigProvider"), K = "arco", X = "$arco", Y = (e) => {
4
+ var a, t, i;
5
+ const r = x(), u = z(H, void 0), l = (i = (t = u == null ? void 0 : u.prefixCls) != null ? t : (a = r == null ? void 0 : r.appContext.config.globalProperties[X]) == null ? void 0 : a.classPrefix) != null ? i : K;
6
+ return e ? `${l}-${e}` : l;
7
+ }, Q = Object.prototype.toString;
8
+ function Z(e) {
9
+ return Q.call(e) === "[object Number]" && e === e;
10
+ }
11
+ var ee = (e, a) => {
12
+ for (const [t, i] of a)
13
+ e[t] = i;
14
+ return e;
15
+ };
16
+ const te = P({
17
+ name: "IconLoading",
18
+ props: {
19
+ size: {
20
+ type: [Number, String]
21
+ },
22
+ strokeWidth: {
23
+ type: Number,
24
+ default: 4
25
+ },
26
+ strokeLinecap: {
27
+ type: String,
28
+ default: "butt",
29
+ validator: (e) => ["butt", "round", "square"].includes(e)
30
+ },
31
+ strokeLinejoin: {
32
+ type: String,
33
+ default: "miter",
34
+ validator: (e) => ["arcs", "bevel", "miter", "miter-clip", "round"].includes(e)
35
+ },
36
+ rotate: Number,
37
+ spin: Boolean
38
+ },
39
+ emits: {
40
+ click: (e) => !0
41
+ },
42
+ setup(e, { emit: a }) {
43
+ const t = Y("icon"), i = S(() => [t, `${t}-loading`, { [`${t}-spin`]: e.spin }]), r = S(() => {
44
+ const l = {};
45
+ return e.size && (l.fontSize = Z(e.size) ? `${e.size}px` : e.size), e.rotate && (l.transform = `rotate(${e.rotate}deg)`), l;
46
+ });
47
+ return {
48
+ cls: i,
49
+ innerStyle: r,
50
+ onClick: (l) => {
51
+ a("click", l);
52
+ }
53
+ };
54
+ }
55
+ }), ae = ["stroke-width", "stroke-linecap", "stroke-linejoin"], ne = /* @__PURE__ */ V("path", { d: "M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6" }, null, -1), oe = [
56
+ ne
57
+ ];
58
+ function le(e, a, t, i, r, u) {
59
+ return D(), F("svg", {
60
+ viewBox: "0 0 48 48",
61
+ fill: "none",
62
+ xmlns: "http://www.w3.org/2000/svg",
63
+ stroke: "currentColor",
64
+ class: j(e.cls),
65
+ style: A(e.innerStyle),
66
+ "stroke-width": e.strokeWidth,
67
+ "stroke-linecap": e.strokeLinecap,
68
+ "stroke-linejoin": e.strokeLinejoin,
69
+ onClick: a[0] || (a[0] = (...l) => e.onClick && e.onClick(...l))
70
+ }, oe, 14, ae);
71
+ }
72
+ var g = /* @__PURE__ */ ee(te, [["render", le]]);
73
+ const ie = Object.assign(g, {
74
+ install: (e, a) => {
75
+ var t;
76
+ const i = (t = a == null ? void 0 : a.iconPrefix) != null ? t : "";
77
+ e.component(i + g.name, g);
78
+ }
79
+ });
80
+ const p = /* @__PURE__ */ P({
81
+ name: "MpegtsPlayer",
82
+ props: {
83
+ videoUrl: {
84
+ type: String,
85
+ default: ""
86
+ },
87
+ closeVisibilityChangeListener: {
88
+ type: Boolean,
89
+ default: !1
90
+ },
91
+ autoVisibilityChangeRefresh: {
92
+ type: Boolean,
93
+ default: !1
94
+ },
95
+ autoReload: {
96
+ type: Boolean,
97
+ default: !1
98
+ },
99
+ isLive: {
100
+ type: Boolean,
101
+ default: !0
102
+ },
103
+ controls: {
104
+ type: Boolean,
105
+ default: !1
106
+ },
107
+ currentTime: {
108
+ type: Number,
109
+ default: 0
110
+ },
111
+ stallTimeout: {
112
+ type: Number,
113
+ default: 5e3
114
+ }
115
+ },
116
+ emits: ["loadError", "playSuccess", "loadComplete", "visibilitychange", "timeupdate", "playEnded", "playLoading"],
117
+ setup(e, {
118
+ emit: a
119
+ }) {
120
+ const t = f(null), i = f(null), r = f(!0), u = f(!1), l = f(0);
121
+ let m = 0, h = Date.now();
122
+ const L = () => {
123
+ const n = i.value;
124
+ t.value = c.createPlayer({
125
+ type: "flv",
126
+ // 指定视频类型
127
+ isLive: e.isLive,
128
+ // 开启直播
129
+ hasAudio: !1,
130
+ // 关闭声音
131
+ cors: !0,
132
+ // 开启跨域访问
133
+ url: e.videoUrl
134
+ // 指定流链接
135
+ }, {
136
+ enableWorker: !1,
137
+ // 启用分离的线程进行转换(如果不想看到控制台频繁报错把它设置为false,官方的回答是这个属性还不稳定,所以要测试实时视频流的话设置为true控制台经常报错)
138
+ // @ts-ignore
139
+ enableWorkerForMSE: !1,
140
+ enableStashBuffer: !e.isLive,
141
+ // 关闭IO隐藏缓冲区(如果需要最小延迟,则设置为false,此项设置针对直播视频流)
142
+ stashInitialSize: 128,
143
+ // 减少首帧等待时长(针对实时视频流)
144
+ lazyLoad: !1,
145
+ // 关闭懒加载模式(针对实时视频流)
146
+ lazyLoadMaxDuration: 0.2,
147
+ // 懒加载的最大时长。单位:秒。建议针对直播:调整为200毫秒
148
+ deferLoadAfterSourceOpen: !1,
149
+ // 在MediaSource sourceopen事件触发后加载。在Chrome上,在后台打开的标签页可能不会触发sourceopen事件,除非切换到该标签页。
150
+ liveBufferLatencyChasing: !!e.isLive,
151
+ // 追踪内部缓冲区导致的实时流延迟
152
+ liveBufferLatencyMaxLatency: 1,
153
+ // HTMLMediaElement 中可接受的最大缓冲区延迟(以秒为单位)之前使用flv.js发现延时严重,还有延时累加的问题,而mpegts.js对此做了优化,不需要我们自己设置快进追帧了
154
+ liveBufferLatencyMinRemain: 0.5,
155
+ // HTMLMediaElement 中可接受的最小缓冲区延迟(以秒为单位)
156
+ autoCleanupSourceBuffer: !0,
157
+ // 自动清理SourceBuffer,防止缓冲区溢出。
158
+ autoCleanupMinBackwardDuration: 30,
159
+ // 自动清理时保留的最小回溯时长。
160
+ autoCleanupMaxBackwardDuration: 60
161
+ // 自动清理时的最大回溯时长。
162
+ }), t.value.attachMediaElement(n), r.value = !0, M(), $();
163
+ }, M = async () => {
164
+ try {
165
+ t.value.load();
166
+ } catch (n) {
167
+ console.log(n), a("loadError", n);
168
+ }
169
+ }, $ = () => {
170
+ t.value.on(c.Events.ERROR, C), t.value.on(c.Events.LOADING_COMPLETE, b), t.value.on(c.Events.STATISTICS_INFO, T);
171
+ }, C = (n, o, s) => {
172
+ console.log(`类型:${JSON.stringify(n)}`, `报错内容${o}`, "报错信息", s), a("loadError", o);
173
+ }, b = (n, o, s) => {
174
+ console.log(`类型:${JSON.stringify(n)}`, `报错内容${o}`, "报错信息", s), console.log("直播已结束"), a("loadComplete"), e.autoReload && B();
175
+ }, T = (n) => {
176
+ const o = n.decodedFrames, s = Date.now();
177
+ o === m && o !== 0 ? s - h > e.stallTimeout && (console.log(`解码帧数超过 ${e.stallTimeout / 1e3} 秒没有更新,可能卡顿了`), a("playLoading")) : (m = o, h = s);
178
+ }, B = () => {
179
+ console.log("自动加载", l.value), l.value++, l.value <= 2 ? v() : l.value = 0;
180
+ }, v = () => {
181
+ t.value != null && d(), L();
182
+ }, N = () => t.value.play(), _ = () => t.value.pause(), d = () => {
183
+ var n, o, s, E;
184
+ t.value && (t.value.off(c.Events.ERROR, C), t.value.off(c.Events.LOADING_COMPLETE, b), (n = t.value) == null || n.pause(), (o = t.value) == null || o.unload(), (s = t.value) == null || s.detachMediaElement(), (E = t.value) == null || E.destroy(), t.value = null);
185
+ }, w = async (n) => {
186
+ var o;
187
+ if (!(!((o = n.target) != null && o.paused) || !r.value)) {
188
+ r.value = !1, console.log("handleCanplay", n.target.paused), l.value = 0, u.value = !1;
189
+ try {
190
+ await t.value.play(), console.log(t.value), a("playSuccess");
191
+ } catch (s) {
192
+ console.log("play error", s), a("loadError", s);
193
+ }
194
+ }
195
+ }, O = () => {
196
+ u.value = !0;
197
+ }, R = (n) => {
198
+ var o;
199
+ a("timeupdate", ((o = n == null ? void 0 : n.target) == null ? void 0 : o.currentTime) ?? 0);
200
+ }, I = () => {
201
+ a("playEnded");
202
+ }, k = () => {
203
+ document.visibilityState === "visible" ? (a("visibilitychange", document.visibilityState), e.autoVisibilityChangeRefresh && v()) : d();
204
+ };
205
+ return U(() => e.videoUrl, (n) => {
206
+ n && G(() => {
207
+ t.value != null && d(), console.log(`isSupported: ${c.isSupported()}`), console.log(`是否支持点播视频:${c.getFeatureList().msePlayback}`), console.log(`是否支持httpflv直播流:${c.getFeatureList().mseLivePlayback}`), L();
208
+ });
209
+ }, {
210
+ immediate: !0
211
+ }), W(() => {
212
+ e.closeVisibilityChangeListener || document.addEventListener("visibilitychange", k);
213
+ }), J(() => {
214
+ d(), e.closeVisibilityChangeListener || document.removeEventListener("visibilitychange", k);
215
+ }), {
216
+ flvPlayer: t,
217
+ videoContainerRef: i,
218
+ loadMetaData: u,
219
+ start: N,
220
+ pause: _,
221
+ destroy: d,
222
+ reload: v,
223
+ handleCanplay: w,
224
+ handleLoadedmetadata: O,
225
+ handleTimeupdate: R,
226
+ handlePlayEnded: I
227
+ };
228
+ },
229
+ render() {
230
+ return y("div", {
231
+ class: "mainContainer"
232
+ }, [y("video", {
233
+ class: "video-container",
234
+ ref: "videoContainerRef",
235
+ muted: !0,
236
+ controls: this.controls,
237
+ onClick: (e) => e.preventDefault(),
238
+ onCanplay: this.handleCanplay,
239
+ onLoadedmetadata: this.handleLoadedmetadata,
240
+ onTimeupdate: this.handleTimeupdate,
241
+ onEnded: this.handlePlayEnded
242
+ }, [q("Your browser is too old which doesn't support HTML5 video.")]), this.loadMetaData && y(ie, {
243
+ class: "meta-data-loading"
244
+ }, null)]);
245
+ }
246
+ }), ce = Object.assign(p, {
247
+ install: (e) => {
248
+ e.component(p.name, p);
249
+ }
250
+ });
251
+ export {
252
+ ce as default
253
+ };
package/package.json CHANGED
@@ -1,48 +1,50 @@
1
- {
2
- "name": "@linker-design-plus/mpegtsplayer",
3
- "version": "1.0.0",
4
- "description": "A player base on mpegts.js",
5
- "main": "dist/index.js",
6
- "module": "dist/index.mjs",
7
- "types": "dist/index.d.ts",
8
- "publishConfig": {
9
- "registry": "https://registry.npmjs.org/",
10
- "access": "public"
11
- },
12
- "files": [
13
- "dist",
14
- "src/MpegtsPlayer.less"
15
- ],
16
- "keywords": [
17
- "vue",
18
- "mpegts",
19
- "mpegts-player"
20
- ],
21
- "author": "Linker Design Team",
22
- "license": "MIT",
23
- "peerDependencies": {
24
- "vue": "^3.1.0",
25
- "mpegts.js": "1.7.3",
26
- "@arco-design/web-vue": "2.56.3"
27
- },
28
- "dependencies": {
29
- "vue": "^3.1.0",
30
- "@arco-design/web-vue": "^2.0.0",
31
- "mpegts.js": "1.7.3"
32
- },
33
- "devDependencies": {
34
- "@types/node": "^18.0.0",
35
- "rimraf": "^5.0.0",
36
- "typescript": "^5.0.0",
37
- "vite": "^4.0.0"
38
- },
39
- "scripts": {
40
- "startup": "pnpm build",
41
- "dev": "node scripts/build.mjs -w",
42
- "build": "pnpm clean && pnpm build:bundle && pnpm build:types",
43
- "build:types": "tsc -p ./tsconfig.json --emitDeclarationOnly",
44
- "build:bundle": "node scripts/build.mjs",
45
- "build:dev": "tsc",
46
- "clean": "rimraf ./dist"
47
- }
1
+ {
2
+ "name": "@linker-design-plus/mpegtsplayer",
3
+ "version": "1.0.2",
4
+ "description": "A player base on mpegts.js",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "publishConfig": {
9
+ "registry": "https://registry.npmjs.org/",
10
+ "access": "public"
11
+ },
12
+ "scripts": {
13
+ "startup": "pnpm build",
14
+ "dev": "node scripts/build.mjs -w",
15
+ "build": "pnpm clean && pnpm build:bundle && pnpm build:types",
16
+ "build:types": "tsc -p ./tsconfig.json --emitDeclarationOnly",
17
+ "build:bundle": "node scripts/build.mjs",
18
+ "build:dev": "tsc",
19
+ "clean": "rimraf ./dist"
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "src/MpegtsPlayer.less"
24
+ ],
25
+ "keywords": [
26
+ "vue",
27
+ "mpegts",
28
+ "mpegts-player"
29
+ ],
30
+ "author": "Linker Design Team",
31
+ "license": "MIT",
32
+ "peerDependencies": {
33
+ "vue": "^3.1.0",
34
+ "mpegts.js": "1.7.3",
35
+ "@arco-design/web-vue": "2.56.3"
36
+ },
37
+ "dependencies": {
38
+ "vue": "^3.1.0",
39
+ "@arco-design/web-vue": "^2.0.0",
40
+ "mpegts.js": "1.7.3"
41
+ },
42
+ "devDependencies": {
43
+ "@types/node": "^18.0.0",
44
+ "rimraf": "^5.0.0",
45
+ "typescript": "^5.0.0",
46
+ "vite": "^4.0.0",
47
+ "@vitejs/plugin-vue": "^4.0.0",
48
+ "@vitejs/plugin-vue-jsx": "^3.0.0"
49
+ }
48
50
  }
@@ -1,23 +1,23 @@
1
- .mainContainer {
2
- display: block;
3
- width: 100%;
4
- height: 100%;
5
- margin-left: auto;
6
- margin-right: auto;
7
- position: relative;
8
- }
9
-
10
- .meta-data-loading {
11
- position: absolute;
12
- top: 50%;
13
- left: 50%;
14
- margin-top: -20px; /* 子元素高度的一半 */
15
- margin-left: -20px; /* 子元素宽度的一半 */
16
- font-size: 40px;
17
- color: rgb(var(--primary-6));
18
- }
19
-
20
- .video-container {
21
- width: 100%;
22
- height: 100%;
1
+ .mainContainer {
2
+ display: block;
3
+ width: 100%;
4
+ height: 100%;
5
+ margin-left: auto;
6
+ margin-right: auto;
7
+ position: relative;
8
+ }
9
+
10
+ .meta-data-loading {
11
+ position: absolute;
12
+ top: 50%;
13
+ left: 50%;
14
+ margin-top: -20px; /* 子元素高度的一半 */
15
+ margin-left: -20px; /* 子元素宽度的一半 */
16
+ font-size: 40px;
17
+ color: rgb(var(--primary-6));
18
+ }
19
+
20
+ .video-container {
21
+ width: 100%;
22
+ height: 100%;
23
23
  }