diff --git a/frontend-tools/chapters-editor/client/src/components/TimelineControls.tsx b/frontend-tools/chapters-editor/client/src/components/TimelineControls.tsx index 1f609713..18263066 100644 --- a/frontend-tools/chapters-editor/client/src/components/TimelineControls.tsx +++ b/frontend-tools/chapters-editor/client/src/components/TimelineControls.tsx @@ -26,6 +26,18 @@ const mediaPageLinkStyles = { }, } as const; +// Helper function to parse time string (HH:MM:SS.mmm) to seconds +const parseTimeToSeconds = (timeString: string): number => { + const parts = timeString.split(':'); + if (parts.length !== 3) return 0; + + const hours = parseInt(parts[0], 10) || 0; + const minutes = parseInt(parts[1], 10) || 0; + const seconds = parseFloat(parts[2]) || 0; + + return hours * 3600 + minutes * 60 + seconds; +}; + interface TimelineControlsProps { currentTime: number; duration: number; @@ -191,7 +203,17 @@ const TimelineControls = ({ setIsAutoSaving(true); // Format segments data for API request - use ref to get latest segments and sort by start time + // ONLY save chapters that have custom titles - filter out chapters without titles or with default names const chapters = clipSegmentsRef.current + .filter((segment) => { + // Filter out empty titles + if (!segment.chapterTitle || !segment.chapterTitle.trim()) { + return false; + } + // Filter out default chapter names like "Chapter 1", "Chapter 2", etc. + const isDefaultName = /^Chapter \d+$/.test(segment.chapterTitle); + return !isDefaultName; + }) .sort((a, b) => a.startTime - b.startTime) // Sort by start time chronologically .map((chapter) => ({ startTime: formatDetailedTime(chapter.startTime), @@ -199,7 +221,7 @@ const TimelineControls = ({ chapterTitle: chapter.chapterTitle, })); - logger.debug('chapters', chapters); + logger.debug('Filtered chapters (only custom titles):', chapters); const mediaId = (typeof window !== 'undefined' && (window as any).MEDIA_DATA?.mediaId) || null; // For testing, use '1234' if no mediaId is available @@ -207,12 +229,13 @@ const TimelineControls = ({ logger.debug('mediaId', finalMediaId); - if (!finalMediaId || chapters.length === 0) { - logger.debug('No mediaId or segments, skipping auto-save'); + if (!finalMediaId) { + logger.debug('No mediaId, skipping auto-save'); setIsAutoSaving(false); return; } + // Save chapters (empty array if no chapters have titles) logger.debug('Auto-saving segments:', { mediaId: finalMediaId, chapters }); const response = await autoSaveVideo(finalMediaId, { chapters }); @@ -499,11 +522,20 @@ const TimelineControls = ({ try { // Format chapters data for API request - sort by start time first + // ONLY save chapters that have custom titles - filter out chapters without titles or with default names const chapters = clipSegments - .filter((segment) => segment.chapterTitle && segment.chapterTitle.trim()) + .filter((segment) => { + // Filter out empty titles + if (!segment.chapterTitle || !segment.chapterTitle.trim()) { + return false; + } + // Filter out default chapter names like "Chapter 1", "Chapter 2", etc. + const isDefaultName = /^Chapter \d+$/.test(segment.chapterTitle); + return !isDefaultName; + }) .sort((a, b) => a.startTime - b.startTime) // Sort by start time chronologically .map((segment) => ({ - chapterTitle: segment.chapterTitle || `Chapter ${segment.id}`, + chapterTitle: segment.chapterTitle, from: formatDetailedTime(segment.startTime), to: formatDetailedTime(segment.endTime), }));