improved preloading
This commit is contained in:
parent
d98ab24f6e
commit
42cc3456eb
@ -20,10 +20,10 @@ export const PRELOAD_CONFIG = {
|
|||||||
currentPage: 1000,
|
currentPage: 1000,
|
||||||
neighborBase: 500,
|
neighborBase: 500,
|
||||||
assetType: {
|
assetType: {
|
||||||
|
transition: 150, // Transitions preloaded for faster start
|
||||||
image: 100, // Backgrounds load first
|
image: 100, // Backgrounds load first
|
||||||
audio: 50,
|
audio: 50,
|
||||||
video: 30,
|
video: 30,
|
||||||
// Note: transitions are cached on first playback, not preloaded
|
|
||||||
} as Record<string, number>,
|
} as Record<string, number>,
|
||||||
variant: {
|
variant: {
|
||||||
thumbnail: 50,
|
thumbnail: 50,
|
||||||
@ -68,11 +68,11 @@ export const PRELOAD_CONFIG = {
|
|||||||
// Partial preload settings (online mode only)
|
// Partial preload settings (online mode only)
|
||||||
// Download only first N bytes of videos/audio for faster Phase 1 completion
|
// Download only first N bytes of videos/audio for faster Phase 1 completion
|
||||||
// Playback uses presigned URL directly (browser handles remaining buffering)
|
// Playback uses presigned URL directly (browser handles remaining buffering)
|
||||||
// Note: Transitions are cached on first playback, not preloaded
|
|
||||||
partialPreload: {
|
partialPreload: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
videoMaxBytes: 5 * 1024 * 1024, // 5MB (~5 seconds of video)
|
videoMaxBytes: 5 * 1024 * 1024, // 5MB (~5 seconds of video)
|
||||||
audioMaxBytes: 512 * 1024, // 512KB (~5 seconds of audio)
|
audioMaxBytes: 512 * 1024, // 512KB (~5 seconds of audio)
|
||||||
|
transitionMaxBytes: 3 * 1024 * 1024, // 3MB (~3 seconds of transition video)
|
||||||
},
|
},
|
||||||
|
|
||||||
// Asset URL field names in element content_json (camelCase)
|
// Asset URL field names in element content_json (camelCase)
|
||||||
|
|||||||
@ -74,14 +74,12 @@ function extractAssetsFromContent(
|
|||||||
for (const [key, value] of Object.entries(obj)) {
|
for (const [key, value] of Object.entries(obj)) {
|
||||||
if (typeof value === 'string' && value && urlFields.includes(key)) {
|
if (typeof value === 'string' && value && urlFields.includes(key)) {
|
||||||
// Classify asset type based on field name
|
// Classify asset type based on field name
|
||||||
// Skip transition fields - transitions are cached on first playback
|
|
||||||
const lowerKey = key.toLowerCase();
|
const lowerKey = key.toLowerCase();
|
||||||
if (lowerKey.includes('transition')) {
|
|
||||||
continue; // Skip transitions
|
|
||||||
}
|
|
||||||
|
|
||||||
let assetType: 'video' | 'audio' | 'image';
|
let assetType: 'video' | 'audio' | 'image' | 'transition';
|
||||||
if (lowerKey.includes('video')) {
|
if (lowerKey.includes('transition')) {
|
||||||
|
assetType = 'transition';
|
||||||
|
} else if (lowerKey.includes('video')) {
|
||||||
assetType = 'video';
|
assetType = 'video';
|
||||||
} else if (lowerKey.includes('audio')) {
|
} else if (lowerKey.includes('audio')) {
|
||||||
assetType = 'audio';
|
assetType = 'audio';
|
||||||
@ -239,14 +237,25 @@ export function useNeighborGraph(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add transition videos (transition is eagerly loaded in page_links)
|
// Extract transition videos from page_links for preloading
|
||||||
const matchingLinks = pageLinks.filter(
|
const matchingLinks = pageLinks.filter(
|
||||||
(link) =>
|
(link) =>
|
||||||
link.is_active !== false && pageIds.includes(link.from_pageId || ''),
|
link.is_active !== false && pageIds.includes(link.from_pageId || ''),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Note: Transition videos are NOT extracted for preloading.
|
matchingLinks.forEach((link) => {
|
||||||
// They are cached on first playback via useTransitionPlayback.cacheBlob()
|
// Extract transition video URL from link.transition
|
||||||
|
const transition = link.transition as { video_url?: string } | undefined;
|
||||||
|
if (transition?.video_url && !seenUrls.has(transition.video_url)) {
|
||||||
|
seenUrls.add(transition.video_url);
|
||||||
|
assets.push({
|
||||||
|
url: transition.video_url,
|
||||||
|
pageId: link.from_pageId || '',
|
||||||
|
assetType: 'transition',
|
||||||
|
priority: 0, // Will be calculated later with transition priority
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return assets;
|
return assets;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -529,12 +529,18 @@ export function usePreloadOrchestrator(
|
|||||||
) => {
|
) => {
|
||||||
// Helper to determine max bytes for partial preload (online mode only)
|
// Helper to determine max bytes for partial preload (online mode only)
|
||||||
// IMPORTANT: Only applies to NEIGHBOR pages, not the current page
|
// IMPORTANT: Only applies to NEIGHBOR pages, not the current page
|
||||||
|
// Transitions always use partial preload (regardless of page)
|
||||||
const getMaxBytesForAsset = (
|
const getMaxBytesForAsset = (
|
||||||
assetType: 'image' | 'video' | 'audio' | 'transition' | 'other',
|
assetType: 'image' | 'video' | 'audio' | 'transition' | 'other',
|
||||||
isNeighborPage: boolean,
|
isNeighborPage: boolean,
|
||||||
): number | undefined => {
|
): number | undefined => {
|
||||||
if (!PRELOAD_CONFIG.partialPreload.enabled) return undefined;
|
if (!PRELOAD_CONFIG.partialPreload.enabled) return undefined;
|
||||||
|
|
||||||
|
// Transitions always use partial preload - they need just enough to start quickly
|
||||||
|
if (assetType === 'transition') {
|
||||||
|
return PRELOAD_CONFIG.partialPreload.transitionMaxBytes;
|
||||||
|
}
|
||||||
|
|
||||||
// Current page assets should be fully downloaded for best UX
|
// Current page assets should be fully downloaded for best UX
|
||||||
if (!isNeighborPage) return undefined;
|
if (!isNeighborPage) return undefined;
|
||||||
|
|
||||||
@ -557,11 +563,6 @@ export function usePreloadOrchestrator(
|
|||||||
assetType: 'image' | 'video' | 'audio' | 'transition' | 'other',
|
assetType: 'image' | 'video' | 'audio' | 'transition' | 'other',
|
||||||
pageId: string,
|
pageId: string,
|
||||||
): Promise<void> | null => {
|
): Promise<void> | null => {
|
||||||
// Skip transitions - they're cached on first playback via useTransitionPlayback
|
|
||||||
if (assetType === 'transition') {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const resolvedUrl = resolveUrl(storageKey, presignedUrls);
|
const resolvedUrl = resolveUrl(storageKey, presignedUrls);
|
||||||
if (!resolvedUrl) return null;
|
if (!resolvedUrl) return null;
|
||||||
|
|
||||||
@ -577,8 +578,9 @@ export function usePreloadOrchestrator(
|
|||||||
// Determine if partial preload applies (neighbor pages only, media files only)
|
// Determine if partial preload applies (neighbor pages only, media files only)
|
||||||
const isNeighborPage = pageId !== currentPageId;
|
const isNeighborPage = pageId !== currentPageId;
|
||||||
const maxBytes = getMaxBytesForAsset(assetType, isNeighborPage);
|
const maxBytes = getMaxBytesForAsset(assetType, isNeighborPage);
|
||||||
// For partial downloads, don't create blob URL - playback uses presigned URL
|
// Create blob URL for images (instant navigation) and full downloads
|
||||||
const createBlobUrl = maxBytes === undefined;
|
// Partial downloads (video/audio/transition) use presigned URL directly for playback
|
||||||
|
const createBlobUrl = assetType === 'image' || maxBytes === undefined;
|
||||||
|
|
||||||
return downloadManager
|
return downloadManager
|
||||||
.addJob({
|
.addJob({
|
||||||
@ -690,11 +692,11 @@ export function usePreloadOrchestrator(
|
|||||||
// ============================================
|
// ============================================
|
||||||
// PHASE 2: Preload everything else (don't wait)
|
// PHASE 2: Preload everything else (don't wait)
|
||||||
// - Current page element assets (full downloads)
|
// - Current page element assets (full downloads)
|
||||||
// - Transition videos (partial preload - 3MB)
|
|
||||||
// - Neighbor page backgrounds (partial preload for video/audio)
|
// - Neighbor page backgrounds (partial preload for video/audio)
|
||||||
// - Neighbor page element assets (partial preload for video/audio)
|
// - Neighbor page element assets (partial preload for video/audio)
|
||||||
|
// - Transition videos from page links (partial preload - 3MB)
|
||||||
// ============================================
|
// ============================================
|
||||||
logger.info('[PRELOAD] Phase 2: Preloading transitions and neighbors');
|
logger.info('[PRELOAD] Phase 2: Preloading neighbors and transitions');
|
||||||
|
|
||||||
// Current page element assets (moved from Phase 1 for faster startup)
|
// Current page element assets (moved from Phase 1 for faster startup)
|
||||||
const currentPageAssets = assets.filter(
|
const currentPageAssets = assets.filter(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user