@design.estate/dees-wcctools 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,139 +0,0 @@
1
- /**
2
- * MP4Service - Handles client-side video format conversion using Mediabunny
3
- * Uses WebCodecs API for hardware-accelerated encoding (10-50x faster than FFmpeg.wasm)
4
- * @see https://mediabunny.dev/
5
- */
6
- import { Conversion, Input, Output, ALL_FORMATS, BlobSource, Mp4OutputFormat, BufferTarget, } from 'mediabunny';
7
- export class MP4Service {
8
- /**
9
- * Check if WebCodecs is supported in this browser
10
- */
11
- static isSupported() {
12
- return (typeof VideoEncoder !== 'undefined' &&
13
- typeof VideoDecoder !== 'undefined');
14
- }
15
- /**
16
- * Check if H.264 encoding is actually available (not just API presence)
17
- */
18
- static async isEncodingSupported() {
19
- if (!this.isSupported())
20
- return false;
21
- try {
22
- const result = await VideoEncoder.isConfigSupported({
23
- codec: 'avc1.42E01E', // H.264 Baseline
24
- width: 640,
25
- height: 480,
26
- bitrate: 1_000_000,
27
- framerate: 30,
28
- });
29
- return result.supported === true;
30
- }
31
- catch {
32
- return false;
33
- }
34
- }
35
- /**
36
- * Convert WebM blob to MP4 using Mediabunny (hardware accelerated via WebCodecs)
37
- */
38
- async convertToMp4(options) {
39
- const { inputBlob, onProgress } = options;
40
- if (!MP4Service.isSupported()) {
41
- throw new Error('WebCodecs API not supported in this browser. Please use a modern browser (Chrome 94+, Edge 94+, Safari 16.4+, Firefox 130+).');
42
- }
43
- // Check if encoding is actually available (not just API presence)
44
- const encodingSupported = await MP4Service.isEncodingSupported();
45
- if (!encodingSupported) {
46
- throw new Error('Video encoding is not available in your browser. This may be due to missing hardware encoder support or browser configuration. Try using Chrome with hardware acceleration enabled.');
47
- }
48
- onProgress?.({
49
- stage: 'loading',
50
- progress: 0,
51
- message: 'Preparing video for conversion...'
52
- });
53
- try {
54
- // Create input from WebM blob
55
- const input = new Input({
56
- source: new BlobSource(inputBlob),
57
- formats: ALL_FORMATS,
58
- });
59
- onProgress?.({
60
- stage: 'loading',
61
- progress: 20,
62
- message: 'Analyzing input video...'
63
- });
64
- // Create output for MP4
65
- const target = new BufferTarget();
66
- const output = new Output({
67
- format: new Mp4OutputFormat(),
68
- target,
69
- });
70
- onProgress?.({
71
- stage: 'converting',
72
- progress: 30,
73
- message: 'Starting conversion (hardware accelerated)...'
74
- });
75
- // Initialize conversion - let mediabunny auto-detect codecs first
76
- const conversion = await Conversion.init({
77
- input,
78
- output,
79
- });
80
- // Debug: log any issues with the conversion
81
- if (!conversion.isValid) {
82
- console.error('[MP4Service] Conversion invalid. Discarded tracks:', conversion.discardedTracks);
83
- conversion.discardedTracks.forEach((track) => {
84
- console.error('[MP4Service] Track discarded:', track.reason, track);
85
- });
86
- throw new Error(`Conversion invalid: tracks discarded due to codec issues. Check browser console for details.`);
87
- }
88
- console.log('[MP4Service] Conversion valid, utilized tracks:', conversion.utilizedTracks);
89
- // Execute conversion with progress tracking
90
- let lastProgress = 30;
91
- const progressInterval = setInterval(() => {
92
- // Increment progress gradually during conversion
93
- if (lastProgress < 90) {
94
- lastProgress += 5;
95
- onProgress?.({
96
- stage: 'converting',
97
- progress: lastProgress,
98
- message: `Converting... ${lastProgress}%`
99
- });
100
- }
101
- }, 500);
102
- try {
103
- await conversion.execute();
104
- }
105
- finally {
106
- clearInterval(progressInterval);
107
- }
108
- onProgress?.({
109
- stage: 'finalizing',
110
- progress: 95,
111
- message: 'Finalizing MP4 file...'
112
- });
113
- // Get the output buffer
114
- const mp4Buffer = target.buffer;
115
- onProgress?.({
116
- stage: 'finalizing',
117
- progress: 100,
118
- message: 'Conversion complete!'
119
- });
120
- return new Blob([mp4Buffer], { type: 'video/mp4' });
121
- }
122
- catch (error) {
123
- console.error('[MP4Service] Conversion failed:', error);
124
- throw new Error(`Video conversion failed: ${error instanceof Error ? error.message : String(error)}`);
125
- }
126
- }
127
- }
128
- // Singleton instance
129
- let mp4ServiceInstance = null;
130
- export function getMP4Service() {
131
- if (!mp4ServiceInstance) {
132
- mp4ServiceInstance = new MP4Service();
133
- }
134
- return mp4ServiceInstance;
135
- }
136
- // Legacy aliases for compatibility with existing code
137
- export { MP4Service as FFmpegService };
138
- export { getMP4Service as getFFmpegService };
139
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXA0LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90c193ZWIvc2VydmljZXMvbXA0LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7R0FJRztBQUVILE9BQU8sRUFDTCxVQUFVLEVBQ1YsS0FBSyxFQUNMLE1BQU0sRUFDTixXQUFXLEVBQ1gsVUFBVSxFQUNWLGVBQWUsRUFDZixZQUFZLEdBQ2IsTUFBTSxZQUFZLENBQUM7QUFjcEIsTUFBTSxPQUFPLFVBQVU7SUFDckI7O09BRUc7SUFDSCxNQUFNLENBQUMsV0FBVztRQUNoQixPQUFPLENBQ0wsT0FBTyxZQUFZLEtBQUssV0FBVztZQUNuQyxPQUFPLFlBQVksS0FBSyxXQUFXLENBQ3BDLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSCxNQUFNLENBQUMsS0FBSyxDQUFDLG1CQUFtQjtRQUM5QixJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUFFLE9BQU8sS0FBSyxDQUFDO1FBRXRDLElBQUksQ0FBQztZQUNILE1BQU0sTUFBTSxHQUFHLE1BQU0sWUFBWSxDQUFDLGlCQUFpQixDQUFDO2dCQUNsRCxLQUFLLEVBQUUsYUFBYSxFQUFFLGlCQUFpQjtnQkFDdkMsS0FBSyxFQUFFLEdBQUc7Z0JBQ1YsTUFBTSxFQUFFLEdBQUc7Z0JBQ1gsT0FBTyxFQUFFLFNBQVM7Z0JBQ2xCLFNBQVMsRUFBRSxFQUFFO2FBQ2QsQ0FBQyxDQUFDO1lBQ0gsT0FBTyxNQUFNLENBQUMsU0FBUyxLQUFLLElBQUksQ0FBQztRQUNuQyxDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLFlBQVksQ0FBQyxPQUEyQjtRQUM1QyxNQUFNLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxHQUFHLE9BQU8sQ0FBQztRQUUxQyxJQUFJLENBQUMsVUFBVSxDQUFDLFdB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