|
@@ -46,13 +46,23 @@ export default defineComponent({
|
|
|
default: false
|
|
|
}
|
|
|
},
|
|
|
- emits: ['canplay', 'pause', 'togglePlay', 'ended', 'reset', 'close', 'error', 'loadedmetadata'],
|
|
|
+ emits: [
|
|
|
+ 'canplay',
|
|
|
+ 'pause',
|
|
|
+ 'togglePlay',
|
|
|
+ 'ended',
|
|
|
+ 'reset',
|
|
|
+ 'close',
|
|
|
+ 'error',
|
|
|
+ 'loadedmetadata'
|
|
|
+ ],
|
|
|
setup(props, { emit, expose }) {
|
|
|
const videoID = 'video' + Date.now() + Math.floor(Math.random() * 100);
|
|
|
const speedBtnId = 'speed' + Date.now() + Math.floor(Math.random() * 100);
|
|
|
const videoItem = ref();
|
|
|
const { item, isEmtry } = toRefs(props);
|
|
|
const data = reactive({
|
|
|
+ speedInKbps: '0 KB/s',
|
|
|
timer: null as any,
|
|
|
currentTime: 0,
|
|
|
duration: 0,
|
|
@@ -66,6 +76,7 @@ export default defineComponent({
|
|
|
},
|
|
|
defaultSpeed: 1 // 默认速度
|
|
|
});
|
|
|
+ const videoRef = ref();
|
|
|
const contetRef = ref();
|
|
|
|
|
|
watch(
|
|
@@ -166,7 +177,7 @@ export default defineComponent({
|
|
|
nextTick(handlePlayVideo);
|
|
|
});
|
|
|
}
|
|
|
- emit('loadedmetadata', videoItem.value)
|
|
|
+ emit('loadedmetadata', videoItem.value);
|
|
|
});
|
|
|
// 视频开始播放
|
|
|
videoItem.value.on('play', () => {
|
|
@@ -228,6 +239,84 @@ export default defineComponent({
|
|
|
}
|
|
|
);
|
|
|
|
|
|
+ const calculateSpeed = (element: any) => {
|
|
|
+ let previousBytesLoaded = 0;
|
|
|
+ let timer: any = null;
|
|
|
+ let previousTime = Date.now();
|
|
|
+
|
|
|
+ // 缓存检测状态
|
|
|
+ let isBuffering = false;
|
|
|
+ // 缓存检测计时器
|
|
|
+ let bufferTimeout: any = null;
|
|
|
+ // 设定一个检测缓存停止的时间间隔,这里我们设置为2500毫秒(2秒)
|
|
|
+ const BUFFER_CHECK_INTERVAL = 2500;
|
|
|
+
|
|
|
+ function resetDownloadSpeed() {
|
|
|
+ timer = setTimeout(() => {
|
|
|
+ // displayElement.textContent = `视屏下载速度: 0 KB/s`;
|
|
|
+ data.speedInKbps = `0 KB/s`;
|
|
|
+ }, 1500);
|
|
|
+ }
|
|
|
+
|
|
|
+ function buffterCatch() {
|
|
|
+ // 设定一个计时器,检查是否在指定的时间内再次触发了progress事件
|
|
|
+ bufferTimeout = setTimeout(() => {
|
|
|
+ if (isBuffering) {
|
|
|
+ // 如果计时器到达且isBuffering仍为true,则认为缓存停止
|
|
|
+ console.log('停止缓存数据。');
|
|
|
+ isBuffering = false;
|
|
|
+ data.speedInKbps = '';
|
|
|
+ }
|
|
|
+ }, BUFFER_CHECK_INTERVAL);
|
|
|
+ }
|
|
|
+
|
|
|
+ element.addEventListener('progress', () => {
|
|
|
+ const currentTime = Date.now();
|
|
|
+ const buffered = element.buffered;
|
|
|
+ let currentBytesLoaded = 0;
|
|
|
+
|
|
|
+ if (buffered.length > 0) {
|
|
|
+ for (let i = 0; i < buffered.length; i++) {
|
|
|
+ currentBytesLoaded += buffered.end(i) - buffered.start(i);
|
|
|
+ }
|
|
|
+ currentBytesLoaded *= element.duration * element.seekable.end(0); // 更精确地近似字节加载量
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('progress', currentBytesLoaded > previousBytesLoaded);
|
|
|
+ if (currentBytesLoaded > previousBytesLoaded) {
|
|
|
+ const timeDiff = (currentTime - previousTime) / 1000; // 时间差转换为秒
|
|
|
+ const bytesDiff = currentBytesLoaded - previousBytesLoaded; // 字节差值
|
|
|
+ const speed = bytesDiff / timeDiff; // 字节每秒
|
|
|
+
|
|
|
+ console.log(timeDiff, bytesDiff, speed);
|
|
|
+
|
|
|
+ const kbps = speed / 1024;
|
|
|
+ const speedInKbps = kbps.toFixed(2); // 转换为千字节每秒并保留两位小数
|
|
|
+ if (kbps > 1024) {
|
|
|
+ data.speedInKbps = `${Number((kbps / 1024).toFixed(2))} M/s`;
|
|
|
+ } else {
|
|
|
+ data.speedInKbps = `${Number(speedInKbps)} KB/s`;
|
|
|
+ }
|
|
|
+
|
|
|
+ previousBytesLoaded = currentBytesLoaded;
|
|
|
+ previousTime = currentTime;
|
|
|
+
|
|
|
+ // 如果1秒钟没有返回就重置数据
|
|
|
+ clearTimeout(timer);
|
|
|
+ resetDownloadSpeed();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果有缓存检测计时器,则清除它
|
|
|
+ if (bufferTimeout) {
|
|
|
+ clearTimeout(bufferTimeout);
|
|
|
+ }
|
|
|
+ // 标记为正在缓存
|
|
|
+ isBuffering = true;
|
|
|
+
|
|
|
+ buffterCatch();
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
onMounted(() => {
|
|
|
videoItem.value = TCPlayer(videoID, {
|
|
|
appID: '',
|
|
@@ -239,6 +328,10 @@ export default defineComponent({
|
|
|
e.stopPropagation();
|
|
|
data.speedControl = !data.speedControl;
|
|
|
});
|
|
|
+
|
|
|
+ nextTick(() => {
|
|
|
+ calculateSpeed(videoRef.value);
|
|
|
+ });
|
|
|
});
|
|
|
|
|
|
const pause = () => {
|
|
@@ -256,6 +349,7 @@ export default defineComponent({
|
|
|
<video
|
|
|
style={{ width: '100%', height: '100%' }}
|
|
|
id={videoID}
|
|
|
+ ref={videoRef}
|
|
|
preload="auto"
|
|
|
playsinline
|
|
|
webkit-playsinline
|
|
@@ -319,6 +413,8 @@ export default defineComponent({
|
|
|
<div class={styles.actionBtn} id={speedBtnId}>
|
|
|
<img src={iconSpeed} />
|
|
|
</div>
|
|
|
+
|
|
|
+ <div class={styles.downloadSpeed}>{data.speedInKbps}</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|