1
0
mirror of https://github.com/immich-app/immich.git synced 2025-06-23 04:38:12 +02:00

fix(web): buffering for video player (#520)

* fix(web): buffering for video player

* chore(): missing file -_-

* refactor(web): using URL builder

* chore(): add semicolon

* fix(web): video player

* remove deadcode

Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
Thanh Pham
2022-08-24 10:21:41 +07:00
committed by GitHub
parent 3b55cdc0be
commit fb0fa742f5
4 changed files with 67 additions and 95 deletions

View File

@ -6,7 +6,7 @@
import PlayCircleOutline from 'svelte-material-icons/PlayCircleOutline.svelte';
import PauseCircleOutline from 'svelte-material-icons/PauseCircleOutline.svelte';
import LoadingSpinner from './loading-spinner.svelte';
import { api, AssetResponseDto, AssetTypeEnum, ThumbnailFormat } from '@api';
import { api, AssetResponseDto, AssetTypeEnum, getFileUrl, ThumbnailFormat } from '@api';
const dispatch = createEventDispatcher();
@ -18,7 +18,7 @@
export let isExisted: boolean = false;
let imageData: string;
let videoData: string;
// let videoData: string;
let mouseOver: boolean = false;
$: dispatch('mouseEvent', { isMouseOver: mouseOver, selectedGroupIndex: groupIndex });
@ -28,7 +28,8 @@
let isThumbnailVideoPlaying = false;
let calculateVideoDurationIntervalHandler: NodeJS.Timer;
let videoProgress = '00:00';
let videoAbortController: AbortController;
// let videoAbortController: AbortController;
let videoUrl: string;
const loadImageData = async () => {
const { data } = await api.assetApi.getAssetThumbnail(asset.id, format, {
@ -42,51 +43,8 @@
const loadVideoData = async () => {
isThumbnailVideoPlaying = false;
videoAbortController = new AbortController();
try {
const { data } = await api.assetApi.serveFile(
asset.deviceAssetId,
asset.deviceId,
false,
true,
{
responseType: 'blob',
signal: videoAbortController.signal
}
);
if (!(data instanceof Blob)) {
return;
}
videoData = URL.createObjectURL(data);
videoPlayerNode.src = videoData;
videoPlayerNode.load();
videoPlayerNode.onloadeddata = () => {
console.log('first frame load');
};
videoPlayerNode.oncanplaythrough = () => {
console.log('can play through');
};
videoPlayerNode.oncanplay = () => {
console.log('can play');
videoPlayerNode.muted = true;
videoPlayerNode.play();
isThumbnailVideoPlaying = true;
calculateVideoDurationIntervalHandler = setInterval(() => {
videoProgress = getVideoDurationInString(Math.round(videoPlayerNode.currentTime));
}, 1000);
};
return videoData;
} catch (e) {}
videoUrl = getFileUrl(asset.deviceAssetId, asset.deviceId, false, true);
};
const getVideoDurationInString = (currentTime: number) => {
@ -136,12 +94,7 @@
const handleMouseLeaveThumbnail = () => {
mouseOver = false;
// Stop XHR download of video
videoAbortController?.abort();
// Stop video playback
URL.revokeObjectURL(videoData);
videoUrl = '';
clearInterval(calculateVideoDurationIntervalHandler);
@ -149,6 +102,18 @@
videoProgress = '00:00';
};
const handleCanPlay = (ev: Event) => {
const playerNode = ev.target as HTMLVideoElement;
playerNode.muted = true;
playerNode.play();
isThumbnailVideoPlaying = true;
calculateVideoDurationIntervalHandler = setInterval(() => {
videoProgress = getVideoDurationInString(Math.round(playerNode.currentTime));
}, 1000);
};
$: getThumbnailBorderStyle = () => {
if (selected) {
return 'border-[20px] border-immich-primary/20';
@ -259,17 +224,21 @@
{#if mouseOver && asset.type === AssetTypeEnum.Video}
<div class="absolute w-full h-full top-0" on:mouseenter={loadVideoData}>
<video
muted
autoplay
preload="none"
class="h-full object-cover"
width="250px"
style:width={`${thumbnailSize}px`}
bind:this={videoPlayerNode}
>
<track kind="captions" />
</video>
{#if videoUrl}
<video
muted
autoplay
preload="none"
class="h-full object-cover"
width="250px"
style:width={`${thumbnailSize}px`}
on:canplay={handleCanPlay}
bind:this={videoPlayerNode}
>
<source src={videoUrl} type="video/mp4" />
<track kind="captions" />
</video>
{/if}
</div>
{/if}
</div>