File size: 4,149 Bytes
ae238b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Transcription limits and thresholds
// These constants are shared across components to ensure consistency

export const TRANSCRIPTION_LIMITS = {
  // Duration limits (in seconds)
  MIN_DURATION: 3,          // Minimum recommended duration for accuracy
  MAX_DURATION: 180,         // Maximum recommended duration (3 minutes)

  // File size limits (in MB)
  MAX_FILE_SIZE: 100,        // Maximum recommended file size
} as const;

export const WARNING_MESSAGES = {
  TOO_SHORT: {
    title: "Media Too Short",
    message: "Your media file is less than 3 seconds long. This may result in reduced transcription accuracy due to insufficient context for the AI model. For best results, use media files at least 30 seconds long.",
  },
  TOO_LONG: {
    title: "Media Too Long",
    message: "Your media file is longer than 3 minutes. This may exceed server resources and could result in processing failures or timeouts. Consider trimming your media to under 3 minutes for optimal results.",
  },
  VERY_LARGE_FILE: {
    title: "File Too Large",
    message: "Your file exceeds the recommended 100MB limit. This may cause upload failures or processing timeouts. Please use a smaller file or compress your media before uploading.",
  },
} as const;

type WarningType = keyof typeof WARNING_MESSAGES;

interface MediaInfo {
  file: File;
  duration?: number; // Duration in seconds, may not be available immediately
}

/**
 * Get the duration of a media file
 * Returns a promise that resolves with the duration in seconds
 */
export const getMediaDuration = (file: File): Promise<number> => {
  return new Promise((resolve, reject) => {
    const url = URL.createObjectURL(file);

    if (file.type.startsWith('video/')) {
      const video = document.createElement('video');
      video.preload = 'metadata';

      video.onloadedmetadata = () => {
        URL.revokeObjectURL(url);
        resolve(video.duration);
      };

      video.onerror = () => {
        URL.revokeObjectURL(url);
        reject(new Error('Failed to load video metadata'));
      };

      video.src = url;
    } else if (file.type.startsWith('audio/')) {
      const audio = document.createElement('audio');
      audio.preload = 'metadata';

      audio.onloadedmetadata = () => {
        URL.revokeObjectURL(url);
        resolve(audio.duration);
      };

      audio.onerror = () => {
        URL.revokeObjectURL(url);
        reject(new Error('Failed to load audio metadata'));
      };

      audio.src = url;
    } else {
      URL.revokeObjectURL(url);
      reject(new Error('Unsupported media type'));
    }
  });
};

/**
 * Check for transcription warnings based on file size and duration
 * Returns an array of warning types that should be shown to the user
 */
export const checkTranscriptionWarnings = (mediaInfo: MediaInfo): WarningType[] => {
  const warnings: WarningType[] = [];
  const { file, duration } = mediaInfo;

  // Check file size (convert to MB)
  const fileSizeMB = file.size / (1024 * 1024);

  if (fileSizeMB > TRANSCRIPTION_LIMITS.MAX_FILE_SIZE) {
    warnings.push('VERY_LARGE_FILE');
  }

  // Check duration if available
  if (duration !== undefined && !isNaN(duration)) {
    if (duration < TRANSCRIPTION_LIMITS.MIN_DURATION) {
      warnings.push('TOO_SHORT');
    } else if (duration > TRANSCRIPTION_LIMITS.MAX_DURATION) {
      warnings.push('TOO_LONG');
    }
  }

  return warnings;
};


/**
 * Format file size in a human-readable format
 */
export const formatFileSize = (bytes: number): string => {
  if (bytes === 0) return '0 Bytes';

  const k = 1024;
  const sizes = ['Bytes', 'KB', 'MB', 'GB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));

  return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
};

/**
 * Format duration in a human-readable format
 */
export const formatDuration = (seconds: number): string => {
  if (isNaN(seconds) || seconds < 0) return 'Unknown';

  const minutes = Math.floor(seconds / 60);
  const remainingSeconds = Math.floor(seconds % 60);

  if (minutes === 0) {
    return `${remainingSeconds}s`;
  } else {
    return `${minutes}m ${remainingSeconds}s`;
  }
};