-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvideoProcessor.js
141 lines (118 loc) · 5.2 KB
/
videoProcessor.js
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
137
138
139
140
141
const {fetchFile} = FFmpegUtil;
const {FFmpeg} = FFmpegWASM;
let ffmpeg = null;
// Initialize FFmpeg right away
document.addEventListener('DOMContentLoaded', function () {
const videoUploader = document.getElementById('videoUploader');
const videoPlayer = document.getElementById('videoPlayer');
const previewCanvas = document.getElementById('previewCanvas');
const ctxPreview = previewCanvas.getContext('2d', {willReadFrequently: true});
const brightnessControl = document.getElementById('brightness');
const contrastControl = document.getElementById('contrast');
const processButton = document.getElementById('processButton');
const downloadButton = document.getElementById('downloadButton');
let videoFile;
videoUploader.addEventListener('change', handleFileUpload);
videoPlayer.addEventListener('loadedmetadata', setupCanvas);
videoPlayer.addEventListener('play', startPreview);
videoPlayer.addEventListener('pause', stopPreview);
processButton.addEventListener('click', processVideo);
brightnessControl.addEventListener('input', updatePreview);
contrastControl.addEventListener('input', updatePreview);
async function loadFFmpeg() {
if (ffmpeg === null) {
ffmpeg = new FFmpeg();
ffmpeg.on('log', ({message}) => {
const logElement = document.getElementById('ffmpegLog');
logElement.innerHTML = message; // Update log message in the UI
console.log(message); // Also log it to the console
});
try {
await ffmpeg.load({
coreURL: "/assets/core-mt/package/dist/umd/ffmpeg-core.js",
});
console.log('FFmpeg Core is loaded');
} catch (e) {
console.error('Error loading FFmpeg:', e);
// Additional error handling or UI feedback can be added here
}
}
}
function handleFileUpload(event) {
videoFile = event.target.files[0];
if (videoFile) {
const url = URL.createObjectURL(videoFile);
videoPlayer.src = url;
previewCanvas.style.display = 'block';
}
}
function setupCanvas() {
previewCanvas.width = videoPlayer.videoWidth;
previewCanvas.height = videoPlayer.videoHeight;
}
function startPreview() {
drawPreviewFrame();
}
function stopPreview() {
cancelAnimationFrame(drawPreviewFrame);
}
function drawPreviewFrame() {
if (!videoPlayer.paused && !videoPlayer.ended) {
ctxPreview.drawImage(videoPlayer, 0, 0, previewCanvas.width, previewCanvas.height);
let frameData = ctxPreview.getImageData(0, 0, previewCanvas.width, previewCanvas.height);
adjustBrightnessContrast(frameData, parseFloat(brightnessControl.value), parseFloat(contrastControl.value));
ctxPreview.putImageData(frameData, 0, 0);
requestAnimationFrame(drawPreviewFrame);
}
}
function adjustBrightnessContrast(imageData, brightness, contrast) {
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
// Apply brightness
data[i] *= brightness; // Red
data[i + 1] *= brightness; // Green
data[i + 2] *= brightness; // Blue
// Apply contrast
data[i] = truncate(((data[i] - 128) * contrast) + 128);
data[i + 1] = truncate(((data[i + 1] - 128) * contrast) + 128);
data[i + 2] = truncate(((data[i + 2] - 128) * contrast) + 128);
}
}
function truncate(value) {
return Math.min(255, Math.max(0, value));
}
async function processVideo() {
console.log("Processing video...");
try {
await loadFFmpeg();
console.log("FFmpeg loaded.");
// Write file to FFmpeg FS
await ffmpeg.writeFile('input.mp4', await fetchFile(videoFile));
const brightness = brightnessControl.value;
const contrast = contrastControl.value;
const filter = `eq=brightness=${brightness - 1}:contrast=${contrast}`;
console.log("Executing FFmpeg command...");
// Using the new exec method
console.time('exec');
await ffmpeg.exec(['-i', 'input.mp4', '-vf', filter, 'output.mp4']);
console.timeEnd('exec');
console.log("FFmpeg command executed");
// Read the output file
console.log("Reading output file...");
const data = await ffmpeg.readFile('output.mp4');
const url = URL.createObjectURL(new Blob([data.buffer], {type: 'video/mp4'}));
downloadButton.href = url;
downloadButton.download = 'processed-video.mp4';
downloadButton.style.display = 'block';
console.log("Process completed. Download button should be visible.");
} catch (e) {
console.error("Error during video processing:", e);
// Additional error handling or UI feedback can be added here
}
}
function updatePreview() {
if (videoPlayer.paused || videoPlayer.ended) {
drawPreviewFrame();
}
}
});