ckplayer-plus 1.0.7 → 1.1.0
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/README.md +3 -1
- package/dist/ckplayer.js +112 -22
- package/dist/ckplayer.min.js +2 -2
- package/dist/index.cjs +493 -422
- package/dist/index.js +492 -422
- package/dist/mpegts.js/LICENSE +202 -0
- package/dist/react.cjs +511 -425
- package/dist/react.js +510 -425
- package/dist/vue.cjs +499 -418
- package/dist/vue.js +498 -418
- package/package.json +9 -2
- package/types/vue.d.ts +2 -0
package/README.md
CHANGED
|
@@ -108,7 +108,7 @@ React:
|
|
|
108
108
|
|
|
109
109
|
```vue
|
|
110
110
|
<template>
|
|
111
|
-
<CkPlayer :video="url" poster="/poster.png" height="400px" @play="onPlay" />
|
|
111
|
+
<CkPlayer :video="url" :seek="16" poster="/poster.png" height="400px" @play="onPlay" />
|
|
112
112
|
</template>
|
|
113
113
|
|
|
114
114
|
<script>
|
|
@@ -125,6 +125,8 @@ export default {
|
|
|
125
125
|
</script>
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
+
断点续播:`seek` 用 `:seek` 或 `options.seek` 在创建时传入;**不要**在 `@ready` 里再 `player.seek(16)`,否则会重复加载 HLS、取消 `.ts` 分片导致卡住。
|
|
129
|
+
|
|
128
130
|
SSR(Nuxt 等)请用 `<ClientOnly>`,仅在浏览器初始化。
|
|
129
131
|
|
|
130
132
|
## React
|
package/dist/ckplayer.js
CHANGED
|
@@ -141,7 +141,7 @@
|
|
|
141
141
|
cdnFallback:true// getPath 失败时是否回退到 jsDelivr(内网可设 false,并配置 pluginPath)
|
|
142
142
|
};
|
|
143
143
|
// 打包时替换为真实版本;用于 bundler 下 getPath 失效时的 CDN 回退
|
|
144
|
-
var ckplayerPlusDefaultCdn='https://cdn.jsdelivr.net/npm/ckplayer-plus@1.0
|
|
144
|
+
var ckplayerPlusDefaultCdn='https://cdn.jsdelivr.net/npm/ckplayer-plus@1.1.0/dist/';
|
|
145
145
|
function ckplayerEmbed(videoObj){
|
|
146
146
|
/*
|
|
147
147
|
* rightMenu
|
|
@@ -176,6 +176,9 @@
|
|
|
176
176
|
var seekApplyLock=false;//防止并发多次 currentTime 赋值
|
|
177
177
|
var decodeRecoverCount=0;//MEDIA_ERR_DECODE 恢复次数
|
|
178
178
|
var hlsStartPositionUsed=false;//是否已用 hls.js startPosition 处理续播
|
|
179
|
+
var hlsResumeTarget=-1;//HLS 续播目标秒数(避免重复 startLoad 取消分片请求)
|
|
180
|
+
var hlsLoadAt=-1;//最近一次 hls.startLoad 目标
|
|
181
|
+
var hlsLoadTs=0;//最近一次 hls.startLoad 时间戳
|
|
179
182
|
var oldTime=0,playTime=0,firstSeekTime=-1,maxSeeTime=0;//oldTime=记录上次播放时间,playTime=当前播放时间,firstSeekTime=记录第一次拖动的时间,maxSeeTime=看过的最大时间
|
|
180
183
|
var isChangeDef=true;//是否需要重置清晰度
|
|
181
184
|
var playType='';//播放类别,默认='',是通过api接口播放,='button'则判定是通过点击按钮播放
|
|
@@ -210,6 +213,33 @@
|
|
|
210
213
|
var cookieArray=[];//保存当前所有记录
|
|
211
214
|
var focusPause=true;//失去焦点前是否是暂停状态
|
|
212
215
|
var existenceObj=false;//是否使用源码里已有的dom
|
|
216
|
+
/*
|
|
217
|
+
* invokeGlobalFn
|
|
218
|
+
* 功能:安全调用全局函数名(替代 eval(name+'()')),仅允许合法标识符路径,避免任意代码执行
|
|
219
|
+
* @expr 形如 "fnName" 或 "a.b.c" 的全局函数名(可含尾随括号)
|
|
220
|
+
*/
|
|
221
|
+
function invokeGlobalFn(expr){
|
|
222
|
+
if(typeof expr!=='string'){
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
var name=expr.replace(/\(\s*\)\s*;?\s*$/,'').trim();
|
|
226
|
+
if(!/^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*)*$/.test(name)){
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
var parts=name.split('.');
|
|
230
|
+
var ctx=(typeof window!=='undefined')?window:this;
|
|
231
|
+
var fn=ctx;
|
|
232
|
+
for(var i=0;i<parts.length;i++){
|
|
233
|
+
if(fn==null){
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
ctx=fn;
|
|
237
|
+
fn=fn[parts[i]];
|
|
238
|
+
}
|
|
239
|
+
if(typeof fn==='function'){
|
|
240
|
+
return fn.call(ctx);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
213
243
|
/*
|
|
214
244
|
* into
|
|
215
245
|
* 功能:初始化,调用播放器则首先调用该函数
|
|
@@ -414,7 +444,7 @@
|
|
|
414
444
|
}
|
|
415
445
|
var allowCdn=!vars || vars['cdnFallback']!==false;
|
|
416
446
|
var cdn=(typeof window!=='undefined' && window.ckplayerPlusCdn) ? window.ckplayerPlusCdn : ckplayerPlusDefaultCdn;
|
|
417
|
-
if(!allowCdn || !cdn || cdn.indexOf('1.0
|
|
447
|
+
if(!allowCdn || !cdn || cdn.indexOf('1.1.0')>-1){
|
|
418
448
|
// 避免占位版本或显式关闭 CDN 时请求坏地址;交给相对路径或业务 pluginPath
|
|
419
449
|
return folder+'/'+file;
|
|
420
450
|
}
|
|
@@ -730,6 +760,47 @@
|
|
|
730
760
|
applyResumeSeekState(parseResumeSeekFromVars());
|
|
731
761
|
}
|
|
732
762
|
},
|
|
763
|
+
/*
|
|
764
|
+
* hlsSeekTo
|
|
765
|
+
* 功能:HLS 跳转(去重,避免重复 startLoad 取消进行中的 .ts 请求)
|
|
766
|
+
* @force 强制重新加载
|
|
767
|
+
* @returns true=已由 HLS 处理(含 no-op),false=非 HLS 或未处理
|
|
768
|
+
*/
|
|
769
|
+
hlsSeekTo=function(target,force){
|
|
770
|
+
if(!hls || typeof hls.startLoad!=='function' || !video){
|
|
771
|
+
return false;
|
|
772
|
+
}
|
|
773
|
+
if(isNaN(target) || target<0){
|
|
774
|
+
target=0;
|
|
775
|
+
}
|
|
776
|
+
var curTime=video.currentTime || 0;
|
|
777
|
+
if(!force){
|
|
778
|
+
// startPosition / 上次 startLoad 已针对同一续播点,且缓冲已覆盖 → 不再重启
|
|
779
|
+
if(hlsResumeTarget>=0 && Math.abs(hlsResumeTarget-target)<1.5){
|
|
780
|
+
if(timeInBuffered(target) && Math.abs(curTime-target)<2.5){
|
|
781
|
+
return true;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
// 已在目标附近且可播 → 跳过
|
|
785
|
+
if(timeInBuffered(target) && Math.abs(curTime-target)<1.5){
|
|
786
|
+
hlsResumeTarget=target;
|
|
787
|
+
return true;
|
|
788
|
+
}
|
|
789
|
+
// 短时间内重复 seek 同一点 → 跳过(防止 onReady 再 seek 取消分片)
|
|
790
|
+
if(hlsLoadAt>=0 && Math.abs(hlsLoadAt-target)<1.5 && (Date.now()-hlsLoadTs)<4000){
|
|
791
|
+
return true;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
hlsLoadAt=target;
|
|
795
|
+
hlsLoadTs=Date.now();
|
|
796
|
+
hlsResumeTarget=target;
|
|
797
|
+
try{
|
|
798
|
+
hls.startLoad(target);
|
|
799
|
+
}catch(event){
|
|
800
|
+
return false;
|
|
801
|
+
}
|
|
802
|
+
return true;
|
|
803
|
+
},
|
|
733
804
|
/*
|
|
734
805
|
* destroyStreamPlayers
|
|
735
806
|
* 功能:切换地址前销毁 hls/flv/mpegts 实例
|
|
@@ -738,6 +809,9 @@
|
|
|
738
809
|
clearSeekRetry();
|
|
739
810
|
seekApplyLock=false;
|
|
740
811
|
hlsStartPositionUsed=false;
|
|
812
|
+
hlsResumeTarget=-1;
|
|
813
|
+
hlsLoadAt=-1;
|
|
814
|
+
hlsLoadTs=0;
|
|
741
815
|
decodeRecoverCount=0;
|
|
742
816
|
if(hls){
|
|
743
817
|
try{
|
|
@@ -918,6 +992,9 @@
|
|
|
918
992
|
if(firstSeekTime<0){
|
|
919
993
|
firstSeekTime=resumeAt;
|
|
920
994
|
}
|
|
995
|
+
hlsResumeTarget=resumeAt;
|
|
996
|
+
hlsLoadAt=resumeAt;
|
|
997
|
+
hlsLoadTs=Date.now();
|
|
921
998
|
seekTime=0;
|
|
922
999
|
hlsStartPositionUsed=true;
|
|
923
1000
|
clearSeekRetry();
|
|
@@ -930,6 +1007,22 @@
|
|
|
930
1007
|
applyPendingSeek();
|
|
931
1008
|
}
|
|
932
1009
|
});
|
|
1010
|
+
hls.on(Hls.Events.FRAG_BUFFERED, function(event, data){
|
|
1011
|
+
if(hlsResumeTarget<=0 || !data || !data.frag){
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1014
|
+
var fragStart=data.frag.start;
|
|
1015
|
+
var fragEnd=fragStart+data.frag.duration;
|
|
1016
|
+
if(hlsResumeTarget>=fragStart-0.5 && hlsResumeTarget<=fragEnd+0.5){
|
|
1017
|
+
// 续播分片已进入缓冲,解除 waiting
|
|
1018
|
+
if(!waited){
|
|
1019
|
+
waited=true;
|
|
1020
|
+
if(C['buffer']){
|
|
1021
|
+
C['buffer'].hide();
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
});
|
|
933
1026
|
hls.on(Hls.Events.ERROR, function(event, data){
|
|
934
1027
|
var code=9;
|
|
935
1028
|
var message=language['error']['loadingFailed'];
|
|
@@ -1760,15 +1853,10 @@
|
|
|
1760
1853
|
firstSeekTime=t;
|
|
1761
1854
|
}
|
|
1762
1855
|
}
|
|
1763
|
-
// HLS:用 hls.startLoad
|
|
1764
|
-
if(
|
|
1856
|
+
// HLS:用 hls.startLoad 从目标分片加载(去重,避免取消进行中的 .ts)
|
|
1857
|
+
if(hlsSeekTo(t, !!force)){
|
|
1765
1858
|
clearSeekRetry();
|
|
1766
1859
|
seekTime=0;
|
|
1767
|
-
try{
|
|
1768
|
-
hls.startLoad(t);
|
|
1769
|
-
}catch(event){
|
|
1770
|
-
seekTime=t;
|
|
1771
|
-
}
|
|
1772
1860
|
return;
|
|
1773
1861
|
}
|
|
1774
1862
|
var readyEnough=!isUndefined(video.readyState) && video.readyState>=2;
|
|
@@ -2650,7 +2738,7 @@
|
|
|
2650
2738
|
}
|
|
2651
2739
|
else if(valType(ad['front']['closeButtonClick'])=='string'){
|
|
2652
2740
|
try{
|
|
2653
|
-
|
|
2741
|
+
invokeGlobalFn(ad['front']['closeButtonClick']);
|
|
2654
2742
|
}
|
|
2655
2743
|
catch(event){console.error(event);}
|
|
2656
2744
|
}
|
|
@@ -3154,13 +3242,8 @@
|
|
|
3154
3242
|
applyPendingSeek(false);
|
|
3155
3243
|
return player;
|
|
3156
3244
|
}
|
|
3157
|
-
if(
|
|
3245
|
+
if(hlsSeekTo(target, false)){
|
|
3158
3246
|
seekTime=0;
|
|
3159
|
-
try{
|
|
3160
|
-
hls.startLoad(target);
|
|
3161
|
-
}catch(event){
|
|
3162
|
-
seekTime=target;
|
|
3163
|
-
}
|
|
3164
3247
|
return player;
|
|
3165
3248
|
}
|
|
3166
3249
|
try{
|
|
@@ -3552,7 +3635,7 @@
|
|
|
3552
3635
|
fun();
|
|
3553
3636
|
}
|
|
3554
3637
|
if(valType(fun)=='string'){
|
|
3555
|
-
|
|
3638
|
+
invokeGlobalFn(fun);
|
|
3556
3639
|
}
|
|
3557
3640
|
}
|
|
3558
3641
|
else{
|
|
@@ -3585,7 +3668,7 @@
|
|
|
3585
3668
|
fun();
|
|
3586
3669
|
}
|
|
3587
3670
|
if(valType(fun)=='string'){
|
|
3588
|
-
|
|
3671
|
+
invokeGlobalFn(fun);
|
|
3589
3672
|
}
|
|
3590
3673
|
}
|
|
3591
3674
|
else{
|
|
@@ -4145,7 +4228,7 @@
|
|
|
4145
4228
|
var a=createlJsLink(m['title']);
|
|
4146
4229
|
a.attr('data-click',m['click'].toString());
|
|
4147
4230
|
a.click(function(){
|
|
4148
|
-
|
|
4231
|
+
invokeGlobalFn($(this).attr('data-click'));
|
|
4149
4232
|
C['menu'].hide();
|
|
4150
4233
|
});
|
|
4151
4234
|
li.append(a);
|
|
@@ -4880,7 +4963,7 @@
|
|
|
4880
4963
|
vars['next']['click']();
|
|
4881
4964
|
}
|
|
4882
4965
|
else if(valType(vars['next']['click'])=='string'){
|
|
4883
|
-
|
|
4966
|
+
invokeGlobalFn(vars['next']['click']);
|
|
4884
4967
|
}
|
|
4885
4968
|
}
|
|
4886
4969
|
if('link' in vars['next']){
|
|
@@ -6978,7 +7061,7 @@
|
|
|
6978
7061
|
if(!isRetry && (!vars || vars['cdnFallback']!==false)){
|
|
6979
7062
|
var cdn=(typeof window!=='undefined' && window.ckplayerPlusCdn) ? window.ckplayerPlusCdn : ckplayerPlusDefaultCdn;
|
|
6980
7063
|
var m=String(file).match(/\/(hls\.js|flv\.js|mpegts\.js|language)\/([^/?#]+)(?:[?#].*)?$/i);
|
|
6981
|
-
if(cdn && cdn.indexOf('1.0
|
|
7064
|
+
if(cdn && cdn.indexOf('1.1.0')===-1 && m){
|
|
6982
7065
|
if(cdn.slice(-1)!=='/'){
|
|
6983
7066
|
cdn+='/';
|
|
6984
7067
|
}
|
|
@@ -7148,7 +7231,14 @@
|
|
|
7148
7231
|
if (xhr.status === 200) {
|
|
7149
7232
|
if (obj.dataType === 'json') {
|
|
7150
7233
|
try {
|
|
7151
|
-
|
|
7234
|
+
var jsonData;
|
|
7235
|
+
try {
|
|
7236
|
+
jsonData = JSON.parse(xhr.responseText);
|
|
7237
|
+
}
|
|
7238
|
+
catch(parseErr) {
|
|
7239
|
+
jsonData = eval('(' + xhr.responseText + ')');
|
|
7240
|
+
}
|
|
7241
|
+
successFun(jsonData); //回调传递参数
|
|
7152
7242
|
}
|
|
7153
7243
|
catch(event) {
|
|
7154
7244
|
successFun(null);
|