ckplayer-plus 1.1.0 → 1.1.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/ckplayer.js +268 -65
- package/dist/ckplayer.min.js +2 -2
- package/dist/index.cjs +223 -64
- package/dist/index.js +223 -64
- package/dist/react.cjs +227 -67
- package/dist/react.js +227 -67
- package/dist/vue.cjs +230 -68
- package/dist/vue.js +230 -68
- package/package.json +1 -1
- package/types/vue.d.ts +1 -1
package/dist/ckplayer.js
CHANGED
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
backLive:false,//显示返回直播按钮
|
|
94
94
|
seek: 0,//默认需要跳转的秒数
|
|
95
95
|
next: null,//下一集按钮动作
|
|
96
|
-
loaded:
|
|
96
|
+
loaded: null,//加载播放器后调用的函数(仅支持 function)
|
|
97
97
|
plug: '',//使用插件
|
|
98
98
|
duration:0,//视频总时间
|
|
99
99
|
preview: null,//预览图片对象
|
|
@@ -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.1.
|
|
144
|
+
var ckplayerPlusDefaultCdn='https://cdn.jsdelivr.net/npm/ckplayer-plus@1.1.2/dist/';
|
|
145
145
|
function ckplayerEmbed(videoObj){
|
|
146
146
|
/*
|
|
147
147
|
* rightMenu
|
|
@@ -174,9 +174,11 @@
|
|
|
174
174
|
var seekRetryTimer=null;//续播等待缓冲的重试计时器
|
|
175
175
|
var seekRetryCount=0;//续播重试次数
|
|
176
176
|
var seekApplyLock=false;//防止并发多次 currentTime 赋值
|
|
177
|
+
var autoplayPending=false;//自动播放必须等初始化续播完成后才触发
|
|
177
178
|
var decodeRecoverCount=0;//MEDIA_ERR_DECODE 恢复次数
|
|
178
179
|
var hlsStartPositionUsed=false;//是否已用 hls.js startPosition 处理续播
|
|
179
180
|
var hlsResumeTarget=-1;//HLS 续播目标秒数(避免重复 startLoad 取消分片请求)
|
|
181
|
+
var hlsResumeWarmup=false;//HLS 续播先预热首个可解码分片,再定位目标时间
|
|
180
182
|
var hlsLoadAt=-1;//最近一次 hls.startLoad 目标
|
|
181
183
|
var hlsLoadTs=0;//最近一次 hls.startLoad 时间戳
|
|
182
184
|
var oldTime=0,playTime=0,firstSeekTime=-1,maxSeeTime=0;//oldTime=记录上次播放时间,playTime=当前播放时间,firstSeekTime=记录第一次拖动的时间,maxSeeTime=看过的最大时间
|
|
@@ -444,7 +446,7 @@
|
|
|
444
446
|
}
|
|
445
447
|
var allowCdn=!vars || vars['cdnFallback']!==false;
|
|
446
448
|
var cdn=(typeof window!=='undefined' && window.ckplayerPlusCdn) ? window.ckplayerPlusCdn : ckplayerPlusDefaultCdn;
|
|
447
|
-
if(!allowCdn || !cdn || cdn.indexOf('1.1.
|
|
449
|
+
if(!allowCdn || !cdn || cdn.indexOf('1.1.2')>-1){
|
|
448
450
|
// 避免占位版本或显式关闭 CDN 时请求坏地址;交给相对路径或业务 pluginPath
|
|
449
451
|
return folder+'/'+file;
|
|
450
452
|
}
|
|
@@ -589,8 +591,10 @@
|
|
|
589
591
|
player.volume(0);
|
|
590
592
|
player.muted();
|
|
591
593
|
recoveryVolume=true;
|
|
592
|
-
|
|
593
|
-
|
|
594
|
+
// 不使用原生 autoplay 属性:浏览器会在 seek 前开始 play,随后
|
|
595
|
+
// currentTime / pause 等初始化动作会打断其 Promise,导致永久 loading。
|
|
596
|
+
video.attr('preload','auto');
|
|
597
|
+
autoplayPending=true;
|
|
594
598
|
}
|
|
595
599
|
else{
|
|
596
600
|
video.attr('preload','metadata');
|
|
@@ -810,6 +814,7 @@
|
|
|
810
814
|
seekApplyLock=false;
|
|
811
815
|
hlsStartPositionUsed=false;
|
|
812
816
|
hlsResumeTarget=-1;
|
|
817
|
+
hlsResumeWarmup=false;
|
|
813
818
|
hlsLoadAt=-1;
|
|
814
819
|
hlsLoadTs=0;
|
|
815
820
|
decodeRecoverCount=0;
|
|
@@ -985,36 +990,57 @@
|
|
|
985
990
|
if(!resumeAt){
|
|
986
991
|
resumeAt=parseResumeSeekFromVars();
|
|
987
992
|
}
|
|
988
|
-
//
|
|
993
|
+
// HLS 续播:不要用精确秒数做 startPosition(易在分片中部起播导致解码失败/永久 loading)。
|
|
994
|
+
// 对齐目标分片起点加载,等分片从起点缓冲到目标后再一次 currentTime,并强制 play。
|
|
989
995
|
if(resumeAt && resumeAt>0 && (isUndefined(vars['live']) || !vars['live'])){
|
|
990
|
-
hlsConf.startPosition=resumeAt;
|
|
991
996
|
maxSeeTime=Math.max(maxSeeTime,resumeAt);
|
|
992
997
|
if(firstSeekTime<0){
|
|
993
998
|
firstSeekTime=resumeAt;
|
|
994
999
|
}
|
|
1000
|
+
seekTime=resumeAt;
|
|
995
1001
|
hlsResumeTarget=resumeAt;
|
|
996
|
-
|
|
997
|
-
hlsLoadTs=Date.now();
|
|
998
|
-
seekTime=0;
|
|
999
|
-
hlsStartPositionUsed=true;
|
|
1000
|
-
clearSeekRetry();
|
|
1002
|
+
hlsResumeWarmup=true;
|
|
1001
1003
|
}
|
|
1002
1004
|
hls = new Hls(hlsConf);
|
|
1003
1005
|
hls.loadSource(url);
|
|
1004
1006
|
hls.attachMedia(video);
|
|
1005
1007
|
hls.on(Hls.Events.MANIFEST_PARSED, function(){
|
|
1008
|
+
if(hlsResumeWarmup && seekTime>0){
|
|
1009
|
+
var loadAt=hlsPriorLoadTime(seekTime);
|
|
1010
|
+
try{
|
|
1011
|
+
hls.startLoad(loadAt);
|
|
1012
|
+
}catch(event){}
|
|
1013
|
+
// 超时兜底:仍未定位则对齐分片起点起播,避免一直转圈
|
|
1014
|
+
setTimeout(function(){
|
|
1015
|
+
if(!hlsResumeWarmup || !seekTime){return;}
|
|
1016
|
+
var target=seekTime;
|
|
1017
|
+
if(hlsCanSafelySeekTo(target)){
|
|
1018
|
+
finishResumeSeek(target);
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
1021
|
+
var snap=hlsPriorLoadTime(target);
|
|
1022
|
+
hlsResumeWarmup=false;
|
|
1023
|
+
finishResumeSeek(snap);
|
|
1024
|
+
},5000);
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1006
1027
|
if(!hlsStartPositionUsed){
|
|
1007
1028
|
applyPendingSeek();
|
|
1008
1029
|
}
|
|
1009
1030
|
});
|
|
1010
1031
|
hls.on(Hls.Events.FRAG_BUFFERED, function(event, data){
|
|
1032
|
+
if(hlsResumeWarmup && seekTime>0){
|
|
1033
|
+
if(hlsCanSafelySeekTo(seekTime)){
|
|
1034
|
+
finishResumeSeek(seekTime);
|
|
1035
|
+
}
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1011
1038
|
if(hlsResumeTarget<=0 || !data || !data.frag){
|
|
1012
1039
|
return;
|
|
1013
1040
|
}
|
|
1014
1041
|
var fragStart=data.frag.start;
|
|
1015
1042
|
var fragEnd=fragStart+data.frag.duration;
|
|
1016
1043
|
if(hlsResumeTarget>=fragStart-0.5 && hlsResumeTarget<=fragEnd+0.5){
|
|
1017
|
-
// 续播分片已进入缓冲,解除 waiting
|
|
1018
1044
|
if(!waited){
|
|
1019
1045
|
waited=true;
|
|
1020
1046
|
if(C['buffer']){
|
|
@@ -1814,6 +1840,109 @@
|
|
|
1814
1840
|
}catch(event){}
|
|
1815
1841
|
return false;
|
|
1816
1842
|
},
|
|
1843
|
+
/*
|
|
1844
|
+
* hlsFragAround
|
|
1845
|
+
* 功能:查找覆盖指定时间的 HLS 分片(用于对齐关键帧起点)
|
|
1846
|
+
*/
|
|
1847
|
+
hlsFragAround=function(t){
|
|
1848
|
+
if(!hls || isNaN(t) || t<0){
|
|
1849
|
+
return null;
|
|
1850
|
+
}
|
|
1851
|
+
try{
|
|
1852
|
+
var level=-1;
|
|
1853
|
+
if(typeof hls.currentLevel==='number' && hls.currentLevel>=0){
|
|
1854
|
+
level=hls.currentLevel;
|
|
1855
|
+
}
|
|
1856
|
+
else if(typeof hls.firstLevel==='number' && hls.firstLevel>=0){
|
|
1857
|
+
level=hls.firstLevel;
|
|
1858
|
+
}
|
|
1859
|
+
else{
|
|
1860
|
+
level=0;
|
|
1861
|
+
}
|
|
1862
|
+
var details=hls.levels && hls.levels[level] && hls.levels[level].details;
|
|
1863
|
+
var frags=details && details.fragments;
|
|
1864
|
+
if(!frags || !frags.length){
|
|
1865
|
+
return null;
|
|
1866
|
+
}
|
|
1867
|
+
for(var i=0;i<frags.length;i++){
|
|
1868
|
+
var f=frags[i];
|
|
1869
|
+
if(!f){continue;}
|
|
1870
|
+
var start=f.start||0;
|
|
1871
|
+
var end=start+(f.duration||0);
|
|
1872
|
+
if(t>=start-0.05 && t<end+0.05){
|
|
1873
|
+
return f;
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
// 超出末片时回退最后一片
|
|
1877
|
+
return frags[frags.length-1];
|
|
1878
|
+
}catch(event){}
|
|
1879
|
+
return null;
|
|
1880
|
+
},
|
|
1881
|
+
/*
|
|
1882
|
+
* hlsPriorLoadTime
|
|
1883
|
+
* 功能:续播加载起点——优先对齐目标分片起点(该流分片开头通常有 IDR)
|
|
1884
|
+
*/
|
|
1885
|
+
hlsPriorLoadTime=function(t){
|
|
1886
|
+
if(isNaN(t) || t<=0){
|
|
1887
|
+
return 0;
|
|
1888
|
+
}
|
|
1889
|
+
var frag=hlsFragAround(t);
|
|
1890
|
+
if(frag && !isUndefined(frag.start)){
|
|
1891
|
+
return Math.max(0,frag.start);
|
|
1892
|
+
}
|
|
1893
|
+
return Math.max(0,t-12);
|
|
1894
|
+
},
|
|
1895
|
+
/*
|
|
1896
|
+
* hlsCanSafelySeekTo
|
|
1897
|
+
* 功能:目标分片已从分片起点连续缓冲到目标点,才允许 currentTime
|
|
1898
|
+
* 避免分片未完整进入 MSE 时中途 seek 触发 PIPELINE_ERROR_DECODE / 永久 loading
|
|
1899
|
+
*/
|
|
1900
|
+
hlsCanSafelySeekTo=function(t){
|
|
1901
|
+
if(!video || isUndefined(video.buffered) || isNaN(t) || t<0){
|
|
1902
|
+
return false;
|
|
1903
|
+
}
|
|
1904
|
+
if(!timeInBuffered(t)){
|
|
1905
|
+
return false;
|
|
1906
|
+
}
|
|
1907
|
+
var fragStart=hlsPriorLoadTime(t);
|
|
1908
|
+
// 同一连续区间需覆盖分片起点→目标
|
|
1909
|
+
try{
|
|
1910
|
+
var buf=video.buffered;
|
|
1911
|
+
for(var i=0;i<buf.length;i++){
|
|
1912
|
+
var start=buf.start(i);
|
|
1913
|
+
var end=buf.end(i);
|
|
1914
|
+
if(fragStart>=start-0.35 && t<=end+0.15){
|
|
1915
|
+
return true;
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
}catch(event){}
|
|
1919
|
+
return false;
|
|
1920
|
+
},
|
|
1921
|
+
/*
|
|
1922
|
+
* finishResumeSeek
|
|
1923
|
+
* 功能:完成续播定位并恢复播放(清除 loading 卡住)
|
|
1924
|
+
*/
|
|
1925
|
+
finishResumeSeek=function(t){
|
|
1926
|
+
hlsResumeWarmup=false;
|
|
1927
|
+
applySeekToMedia(t);
|
|
1928
|
+
// seeked 可能因解码抖动延迟;主动再拉一次播放,避免永久转圈
|
|
1929
|
+
setTimeout(function(){
|
|
1930
|
+
if(!video){return;}
|
|
1931
|
+
if(C['buffer']){
|
|
1932
|
+
C['buffer'].hide();
|
|
1933
|
+
}
|
|
1934
|
+
waited=true;
|
|
1935
|
+
if(vars['autoplay'] || autoplayPending){
|
|
1936
|
+
try{
|
|
1937
|
+
var p=video.play();
|
|
1938
|
+
if(p && typeof p.then==='function'){
|
|
1939
|
+
p.catch(function(){});
|
|
1940
|
+
}
|
|
1941
|
+
}catch(event){}
|
|
1942
|
+
autoplayPending=false;
|
|
1943
|
+
}
|
|
1944
|
+
},120);
|
|
1945
|
+
},
|
|
1817
1946
|
/*
|
|
1818
1947
|
* clearSeekRetry
|
|
1819
1948
|
* 功能:清理续播等待计时器
|
|
@@ -1825,6 +1954,35 @@
|
|
|
1825
1954
|
}
|
|
1826
1955
|
seekRetryCount=0;
|
|
1827
1956
|
},
|
|
1957
|
+
/*
|
|
1958
|
+
* startPendingAutoplay
|
|
1959
|
+
* 功能:续播定位完成后统一发起一次播放,避免 play/pause 竞态
|
|
1960
|
+
*/
|
|
1961
|
+
startPendingAutoplay=function(){
|
|
1962
|
+
if(!autoplayPending || !video || !vars['autoplay'] || seekTime || seekApplyLock || loadedmetadataNum<1){
|
|
1963
|
+
return;
|
|
1964
|
+
}
|
|
1965
|
+
autoplayPending=false;
|
|
1966
|
+
player.play();
|
|
1967
|
+
},
|
|
1968
|
+
/*
|
|
1969
|
+
* applySeekToMedia
|
|
1970
|
+
* 功能:仅对已建立解码管线的 media 元素写入 currentTime
|
|
1971
|
+
*/
|
|
1972
|
+
applySeekToMedia=function(t){
|
|
1973
|
+
clearSeekRetry();
|
|
1974
|
+
seekApplyLock=true;
|
|
1975
|
+
seekTime=0;
|
|
1976
|
+
try{
|
|
1977
|
+
video.currentTime=t;
|
|
1978
|
+
}catch(event){
|
|
1979
|
+
seekTime=t;
|
|
1980
|
+
seekApplyLock=false;
|
|
1981
|
+
}
|
|
1982
|
+
setTimeout(function(){
|
|
1983
|
+
seekApplyLock=false;
|
|
1984
|
+
},800);
|
|
1985
|
+
},
|
|
1828
1986
|
/*
|
|
1829
1987
|
* applyPendingSeek
|
|
1830
1988
|
* 功能:在媒体就绪且目标时间可解码后再应用挂起的 seekTime
|
|
@@ -1853,15 +2011,41 @@
|
|
|
1853
2011
|
firstSeekTime=t;
|
|
1854
2012
|
}
|
|
1855
2013
|
}
|
|
1856
|
-
// HLS
|
|
1857
|
-
if(
|
|
1858
|
-
|
|
1859
|
-
|
|
2014
|
+
// HLS 首分片尚未完成预热时不能直接 startLoad(target)
|
|
2015
|
+
if(hlsResumeWarmup){
|
|
2016
|
+
if(hlsCanSafelySeekTo(t)){
|
|
2017
|
+
finishResumeSeek(t);
|
|
2018
|
+
}
|
|
1860
2019
|
return;
|
|
1861
2020
|
}
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
2021
|
+
// HLS:用 hls.startLoad 从目标分片起点加载(去重,避免取消进行中的 .ts)
|
|
2022
|
+
if(hls && typeof hls.startLoad==='function'){
|
|
2023
|
+
if(!hlsCanSafelySeekTo(t) && t>1){
|
|
2024
|
+
hlsResumeWarmup=true;
|
|
2025
|
+
hlsResumeTarget=t;
|
|
2026
|
+
try{
|
|
2027
|
+
hls.startLoad(hlsPriorLoadTime(t));
|
|
2028
|
+
}catch(event){}
|
|
2029
|
+
seekRetryCount++;
|
|
2030
|
+
if(seekRetryCount<=50){
|
|
2031
|
+
if(seekRetryTimer){
|
|
2032
|
+
clearTimeout(seekRetryTimer);
|
|
2033
|
+
}
|
|
2034
|
+
seekRetryTimer=setTimeout(function(){
|
|
2035
|
+
applyPendingSeek(false);
|
|
2036
|
+
},200);
|
|
2037
|
+
}
|
|
2038
|
+
return;
|
|
2039
|
+
}
|
|
2040
|
+
if(hlsSeekTo(t, !!force)){
|
|
2041
|
+
clearSeekRetry();
|
|
2042
|
+
seekTime=0;
|
|
2043
|
+
return;
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
// 对普通 MP4,metadata 后设置 currentTime 会由浏览器自动请求目标 Range。
|
|
2047
|
+
// 等待目标已缓冲会形成循环等待:目标分片只有 seek 后才会下载。
|
|
2048
|
+
if(!force && (!isUndefined(video.readyState) && video.readyState<1)){
|
|
1865
2049
|
seekRetryCount++;
|
|
1866
2050
|
if(seekRetryCount<=50){
|
|
1867
2051
|
if(seekRetryTimer){
|
|
@@ -1873,58 +2057,60 @@
|
|
|
1873
2057
|
return;
|
|
1874
2058
|
}
|
|
1875
2059
|
}
|
|
1876
|
-
|
|
1877
|
-
seekApplyLock=true;
|
|
1878
|
-
seekTime=0;
|
|
1879
|
-
try{
|
|
1880
|
-
video.currentTime=t;
|
|
1881
|
-
}catch(event){
|
|
1882
|
-
seekTime=t;
|
|
1883
|
-
seekApplyLock=false;
|
|
1884
|
-
}
|
|
1885
|
-
setTimeout(function(){
|
|
1886
|
-
seekApplyLock=false;
|
|
1887
|
-
},800);
|
|
2060
|
+
applySeekToMedia(t);
|
|
1888
2061
|
},
|
|
1889
2062
|
/*
|
|
1890
2063
|
* recoverDecodeError
|
|
1891
2064
|
* 功能:断点续播触发的解码错误尝试恢复(Chrome PIPELINE_ERROR_DECODE)
|
|
2065
|
+
* 典型场景:目标 TS 分片首帧不是关键帧,必须回退加载前序分片再建解码管线
|
|
1892
2066
|
*/
|
|
1893
2067
|
recoverDecodeError=function(){
|
|
1894
|
-
if(decodeRecoverCount>=
|
|
2068
|
+
if(decodeRecoverCount>=3){
|
|
1895
2069
|
return false;
|
|
1896
2070
|
}
|
|
1897
2071
|
decodeRecoverCount++;
|
|
1898
|
-
var resumeAt=playTime>0?playTime:(vars['seek']?parseFloat(vars['seek']):0);
|
|
2072
|
+
var resumeAt=hlsResumeTarget>0?hlsResumeTarget:(playTime>0?playTime:(vars['seek']?parseFloat(vars['seek']):0));
|
|
1899
2073
|
if(isNaN(resumeAt) || resumeAt<0){
|
|
1900
2074
|
resumeAt=0;
|
|
1901
2075
|
}
|
|
2076
|
+
// 优先对齐分片起点(有 IDR);多次失败再往前一片
|
|
2077
|
+
var loadFrom=hlsPriorLoadTime(resumeAt);
|
|
2078
|
+
if(decodeRecoverCount>=2){
|
|
2079
|
+
loadFrom=Math.max(0,loadFrom-10);
|
|
2080
|
+
}
|
|
2081
|
+
seekApplyLock=false;
|
|
2082
|
+
clearSeekRetry();
|
|
1902
2083
|
try{
|
|
1903
2084
|
if(hls && typeof hls.recoverMediaError==='function'){
|
|
1904
2085
|
hls.recoverMediaError();
|
|
1905
|
-
if(resumeAt>0){
|
|
1906
|
-
seekTime=resumeAt;
|
|
1907
|
-
seekApplyLock=false;
|
|
1908
|
-
setTimeout(function(){
|
|
1909
|
-
applyPendingSeek(true);
|
|
1910
|
-
},300);
|
|
1911
|
-
}
|
|
1912
|
-
return true;
|
|
1913
2086
|
}
|
|
1914
2087
|
}catch(event){}
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
2088
|
+
if(resumeAt>0 && hls && typeof hls.startLoad==='function'){
|
|
2089
|
+
// 第 3 次直接落到分片起点起播,保证能出画面
|
|
2090
|
+
var target=(decodeRecoverCount>=3)?loadFrom:resumeAt;
|
|
2091
|
+
seekTime=target;
|
|
2092
|
+
hlsResumeTarget=resumeAt;
|
|
2093
|
+
hlsResumeWarmup=true;
|
|
2094
|
+
hlsLoadAt=-1;
|
|
2095
|
+
hlsLoadTs=0;
|
|
2096
|
+
try{
|
|
2097
|
+
hls.startLoad(loadFrom);
|
|
2098
|
+
}catch(event){}
|
|
1922
2099
|
setTimeout(function(){
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
2100
|
+
if(hlsCanSafelySeekTo(target)){
|
|
2101
|
+
finishResumeSeek(target);
|
|
2102
|
+
}
|
|
2103
|
+
else if(decodeRecoverCount>=2){
|
|
2104
|
+
finishResumeSeek(loadFrom);
|
|
1926
2105
|
}
|
|
1927
|
-
|
|
2106
|
+
else{
|
|
2107
|
+
applyPendingSeek(false);
|
|
2108
|
+
}
|
|
2109
|
+
},600);
|
|
2110
|
+
return true;
|
|
2111
|
+
}
|
|
2112
|
+
try{
|
|
2113
|
+
finishResumeSeek(Math.max(0,resumeAt-1.5));
|
|
1928
2114
|
return true;
|
|
1929
2115
|
}catch(event){}
|
|
1930
2116
|
return false;
|
|
@@ -1981,6 +2167,7 @@
|
|
|
1981
2167
|
C['loading'].hide();
|
|
1982
2168
|
eventTarget('canplay');
|
|
1983
2169
|
applyPendingSeek();
|
|
2170
|
+
startPendingAutoplay();
|
|
1984
2171
|
},
|
|
1985
2172
|
loadedData:function(){
|
|
1986
2173
|
eventTarget('loadeddata');
|
|
@@ -2036,6 +2223,7 @@
|
|
|
2036
2223
|
}
|
|
2037
2224
|
pSliderMouseDown=false;
|
|
2038
2225
|
loadedmetadataNum++;
|
|
2226
|
+
startPendingAutoplay();
|
|
2039
2227
|
if(!isUndefined(ad) && !isUndefined(ad['frontPlay']) && ad['frontPlay'] && loadedmetadataNum>1){//如果是贴片广告播放中,则进行播放和计算
|
|
2040
2228
|
player.play();
|
|
2041
2229
|
calculationAdFrontTime(duration);//计算贴片广告的时间
|
|
@@ -2119,10 +2307,8 @@
|
|
|
2119
2307
|
if(!isUndefined(errorInfo.message)){
|
|
2120
2308
|
msg=errorInfo.message;
|
|
2121
2309
|
}
|
|
2122
|
-
// code=3 MEDIA_ERR_DECODE
|
|
2310
|
+
// code=3 MEDIA_ERR_DECODE:续播非关键帧常见,先尝试恢复;恢复中不向业务抛致命 error
|
|
2123
2311
|
if(code===3 && recoverDecodeError()){
|
|
2124
|
-
CT.error={code:code,message:msg};
|
|
2125
|
-
eventTarget('error',CT.error);
|
|
2126
2312
|
return;
|
|
2127
2313
|
}
|
|
2128
2314
|
CT.error={code:code,message:msg};
|
|
@@ -2166,8 +2352,8 @@
|
|
|
2166
2352
|
},
|
|
2167
2353
|
stalled:function(){
|
|
2168
2354
|
eventTarget('stalled');//注册监听error
|
|
2169
|
-
|
|
2170
|
-
|
|
2355
|
+
// HLS 在切片预热、切换清晰度时会短暂触发 stalled,属于可恢复缓冲。
|
|
2356
|
+
// 不把它上报为致命 error,避免业务侧误判已失败而覆盖正常播放状态。
|
|
2171
2357
|
},
|
|
2172
2358
|
suspend:function(){
|
|
2173
2359
|
eventTarget('suspend');//注册监听error
|
|
@@ -2180,15 +2366,14 @@
|
|
|
2180
2366
|
seeked:function(){
|
|
2181
2367
|
seekApplyLock=false;
|
|
2182
2368
|
decodeRecoverCount=0;
|
|
2183
|
-
|
|
2184
|
-
player.play();
|
|
2185
|
-
}
|
|
2369
|
+
startPendingAutoplay();
|
|
2186
2370
|
pSliderMouseDown=false;
|
|
2187
2371
|
eventTarget('seek',{time:this.currentTime,state:'seeked'});
|
|
2188
2372
|
eventTarget('seeked');
|
|
2189
2373
|
},
|
|
2190
2374
|
seeking:function(){
|
|
2191
|
-
|
|
2375
|
+
// 续播预热/定位过程中不要抢先 play,否则会打断 play Promise 导致永久 loading
|
|
2376
|
+
if(paused && !seekApplyLock && !hlsResumeWarmup && !seekTime){
|
|
2192
2377
|
player.play();
|
|
2193
2378
|
}
|
|
2194
2379
|
var seekingTime=this.currentTime;
|
|
@@ -3054,7 +3239,14 @@
|
|
|
3054
3239
|
}
|
|
3055
3240
|
else{
|
|
3056
3241
|
if(loadedmetadataNum>0 && video){
|
|
3057
|
-
try{
|
|
3242
|
+
try{
|
|
3243
|
+
var playPromise=video.play();
|
|
3244
|
+
// play() 返回 Promise 时必须消费 rejection,避免 autoplay 策略或
|
|
3245
|
+
// 页面卸载造成未捕获异常;播放状态仍由原生事件同步。
|
|
3246
|
+
if(playPromise && typeof playPromise.catch==='function'){
|
|
3247
|
+
playPromise.catch(function(){});
|
|
3248
|
+
}
|
|
3249
|
+
}catch(event){}
|
|
3058
3250
|
}
|
|
3059
3251
|
}
|
|
3060
3252
|
return player;
|
|
@@ -3242,6 +3434,17 @@
|
|
|
3242
3434
|
applyPendingSeek(false);
|
|
3243
3435
|
return player;
|
|
3244
3436
|
}
|
|
3437
|
+
// HLS:无前序关键帧缓冲时禁止直接 startLoad(target)
|
|
3438
|
+
if(hls && target>1 && !hlsCanSafelySeekTo(target)){
|
|
3439
|
+
seekTime=target;
|
|
3440
|
+
hlsResumeWarmup=true;
|
|
3441
|
+
hlsResumeTarget=target;
|
|
3442
|
+
try{
|
|
3443
|
+
hls.startLoad(hlsPriorLoadTime(target));
|
|
3444
|
+
}catch(event){}
|
|
3445
|
+
applyPendingSeek(false);
|
|
3446
|
+
return player;
|
|
3447
|
+
}
|
|
3245
3448
|
if(hlsSeekTo(target, false)){
|
|
3246
3449
|
seekTime=0;
|
|
3247
3450
|
return player;
|
|
@@ -7061,7 +7264,7 @@
|
|
|
7061
7264
|
if(!isRetry && (!vars || vars['cdnFallback']!==false)){
|
|
7062
7265
|
var cdn=(typeof window!=='undefined' && window.ckplayerPlusCdn) ? window.ckplayerPlusCdn : ckplayerPlusDefaultCdn;
|
|
7063
7266
|
var m=String(file).match(/\/(hls\.js|flv\.js|mpegts\.js|language)\/([^/?#]+)(?:[?#].*)?$/i);
|
|
7064
|
-
if(cdn && cdn.indexOf('1.1.
|
|
7267
|
+
if(cdn && cdn.indexOf('1.1.2')===-1 && m){
|
|
7065
7268
|
if(cdn.slice(-1)!=='/'){
|
|
7066
7269
|
cdn+='/';
|
|
7067
7270
|
}
|
|
@@ -7984,4 +8187,4 @@
|
|
|
7984
8187
|
}
|
|
7985
8188
|
}
|
|
7986
8189
|
return ckplayerEmbed;
|
|
7987
|
-
}));
|
|
8190
|
+
}));
|