video-duration.service.ts 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. import { Injectable } from '@angular/core';
  2. import { VideoGenerationCapability } from '../models/video-generation-capability.model';
  3. @Injectable({ providedIn: 'root' })
  4. export class VideoDurationService {
  5. private readonly fps = 24;
  6. secondsToFrames(seconds: number): number {
  7. const normalized = Math.max(1, Number(seconds) || 5);
  8. return Math.max(1, Math.round(normalized * this.fps) + 1);
  9. }
  10. framesToSeconds(frames: number): number {
  11. const normalized = Math.max(1, Number(frames) || 121);
  12. return Math.max(1, Math.round((normalized - 1) / this.fps));
  13. }
  14. normalizeSeconds(seconds: number, capability: VideoGenerationCapability): number {
  15. const raw = Number(seconds);
  16. const fallback = capability.defaultSeconds || 5;
  17. const value = Number.isFinite(raw) && raw > 0 ? raw : fallback;
  18. return Math.max(capability.minSeconds, Math.min(capability.maxSeconds, Math.round(value)));
  19. }
  20. normalizeToNearestAllowedSeconds(seconds: number, allowedSeconds: number[] = [5, 10], fallback = 5): number {
  21. const value = Math.round(Number(seconds) || fallback);
  22. const candidates = allowedSeconds.filter((item) => Number.isFinite(item) && item > 0);
  23. if (!candidates.length) return fallback;
  24. return candidates.reduce((best, current) => {
  25. const bestDistance = Math.abs(best - value);
  26. const currentDistance = Math.abs(current - value);
  27. return currentDistance < bestDistance ? current : best;
  28. }, candidates[0]);
  29. }
  30. validateDuration(seconds: number, capability: VideoGenerationCapability): string {
  31. if (seconds < capability.minSeconds) return `最短支持 ${capability.minSeconds} 秒`;
  32. if (seconds > capability.maxSeconds) return `最长支持 ${capability.maxSeconds} 秒`;
  33. return '';
  34. }
  35. }