feat(video): add video upload with remux/transcode playback
Add video as a media kind in photos: streaming upload with per-kind limits, ffprobe metadata, poster frame reusing the image variant pipeline, and a playback object (remux when web-compatible, else h264/yuv420p/aac transcode). Video jobs run on a separate pool with a long lease. Frontend gains a video viewer, grid badge/duration and video upload.
This commit is contained in:
@@ -50,6 +50,14 @@
|
||||
|
||||
const isSelected = (id: string) => selectedIds.includes(id);
|
||||
const isCursor = (i: number) => cursorIndex === i;
|
||||
|
||||
function formatDuration(ms?: number): string {
|
||||
if (!ms || ms <= 0) return '';
|
||||
const total = Math.round(ms / 1000);
|
||||
const m = Math.floor(total / 60);
|
||||
const s = total % 60;
|
||||
return `${m}:${String(s).padStart(2, '0')}`;
|
||||
}
|
||||
const tabIndexFor = (i: number) =>
|
||||
cursorIndex == null ? (i === 0 ? 0 : -1) : isCursor(i) ? 0 : -1;
|
||||
|
||||
@@ -117,6 +125,21 @@
|
||||
360
|
||||
</span>
|
||||
{/if}
|
||||
{#if photo.kind === 'video'}
|
||||
<span
|
||||
class="absolute top-1 left-1 inline-flex items-center justify-center rounded bg-black/60 p-1 text-white"
|
||||
aria-label="Видео"
|
||||
>
|
||||
<Icon name="play_arrow" class="size-4" />
|
||||
</span>
|
||||
{#if formatDuration(photo.duration_ms)}
|
||||
<span
|
||||
class="absolute bottom-1 left-1 rounded bg-black/70 px-1.5 py-0.5 text-[10px] font-medium text-white"
|
||||
>
|
||||
{formatDuration(photo.duration_ms)}
|
||||
</span>
|
||||
{/if}
|
||||
{/if}
|
||||
<span
|
||||
class="bg-bg/70 text-text absolute right-1 bottom-1 flex items-center gap-1.5 rounded px-1.5 py-0.5 text-xs"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user