FFMPEG WASM WRITEFILJavascript

Форум по Javascript
Ответить
Anonymous
 FFMPEG WASM WRITEFIL

Сообщение Anonymous »

Я использую ffmpeg webassembly (wasm) в приложении React для обработки и преобразования видеофайла перед его загрузкой. Цель состоит в том, чтобы изменить размер видео до 720p с помощью ffmpeg, прежде чем отправлять его в бэкэнд. работает, чтобы получить файл и подтвердить, что он загружается в память, но ffmpeg висит на ffmpeg.writefile () и не продолжается дальше. Ошибки не выбраны. /p>

Код: Выделить всё

 const loadFFmpeg = async () => {
if (loaded) return; // Avoid reloading if
already loaded

const baseURL = 'https://unpkg.com/@ffmpeg/core@0.12.6/dist/umd';
const ffmpeg = ffmpegRef.current;
ffmpeg.on('log', ({ message }) => {
messageRef.current.innerHTML = message;
console.log(message);
});
await ffmpeg.load({
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
});
setLoaded(true);
};

useEffect(() => {
loadFFmpeg()
}, [])
< /code>
< /li>
[*]  Извлечение и написание файла < /p>
  const convertVideoTo720p = async (videoFile) => {
console.log("Starting video
conversion...");

const { height } = await getVideoMetadata(videoFile);
console.log(`Video height: ${height}`);

if (height 
[*] Обеспечить полностью загрузку ffmpeg перед вызовом writefile () 
✅ ffmpeg.isloaded ()  Возвращает true .
[*] Проверенный процесс избрания файлов:
✅ fetchfile (Videofile)  успешно возвращает uint8array .
[*] Пробовал переименовать файл, чтобы предотвратить кэширование Проблемы
✅ Используют уникальное имя файла, например, видео _ $ {date.now ()}. mp4 , но без изменения
[*] Проверенная консоль браузера для ошибок:
❌ Ошибки не отображаются. Без ffmpeg, поэтому проблема специфична для ffmpeg. < /li>
< /ul>
[b] ожидается Поведение < /strong> < /p>
[list]
[code]ffmpeg.writeFile('input.mp4', fetchedFile);
следует заполнить и разрешить FFMPEG обрабатывать видео.
Остановка выполнения в writefile , и ошибки не допускаются.
[/list]
среда: < /strong> < /p>
  • React: 18.x < /li>
    ffmpeg wasm Версия: @ffmpeg/ffmpeg @0.12.15
  • Браузер: Chrome 121, Edge 120
  • Операционная система: Windows 11
Вопрос: [/b]
Почему ffmpeg's writefile () задерживается и никогда не завершается?
Как я могу исправить или отладить эту проблему? />
import { useNavigate } from "react-router-dom";
import { useEffect, useRef, useState } from 'react';
import { Form, Input, Button, Select, Space } from 'antd';
const { Option } = Select;
import { FaAngleLeft } from "react-icons/fa6";
import { message, Upload } from 'antd';
import { CiCamera } from "react-icons/ci";
import { IoVideocamOutline } from "react-icons/io5";
import { useCreateWorkoutVideoMutation } from "../../../redux/features/workoutVideo/workoutVideoApi";
import { convertVideoTo720p } from "../../../utils/ffmpegHelper";
import { FFmpeg } from '@ffmpeg/ffmpeg';
import { fetchFile, toBlobURL } from '@ffmpeg/util';

const AddWorkoutVideo = () => {
const [videoFile, setVideoFile] = useState(null);
const [imageFile, setImageFile] = useState(null);
const [loaded, setLoaded] = useState(false);
const ffmpegRef = useRef(new FFmpeg());
const videoRef = useRef(null);
const messageRef = useRef(null);
const [form] = Form.useForm();
const [createWorkoutVideo, { isLoading }] = useCreateWorkoutVideoMutation()
const navigate = useNavigate();

const videoFileRef = useRef(null); // Use a ref instead of state

// Handle Video Upload
const handleVideoChange = ({ file }) => {
setVideoFile(file.originFileObj);
};

// Handle Image Upload
const handleImageChange = ({ file }) => {
setImageFile(file.originFileObj);
};

// Load FFmpeg core if needed (optional if you want to preload)
const loadFFmpeg = async () => {
if (loaded) return; // Avoid reloading if already loaded

const baseURL = 'https://unpkg.com/@ffmpeg/core@0.12.6/dist/umd';
const ffmpeg = ffmpegRef.current;
ffmpeg.on('log', ({ message }) => {
messageRef.current.innerHTML = message;
console.log(message);
});
await ffmpeg.load({
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
});
setLoaded(true);
};

useEffect(() => {
loadFFmpeg()
}, [])

// Helper: Get video metadata (width and height)
const getVideoMetadata = (file) => {
return new Promise((resolve, reject) => {
const video = document.createElement('video');
video.preload = 'metadata';
video.onloadedmetadata = () => {
resolve({ width: video.videoWidth, height: video.videoHeight });
};
video.onerror = () => reject(new Error('Could not load video metadata'));
video.src = URL.createObjectURL(file);
});
};

// Inline conversion helper function
// const convertVideoTo720p = async (videoFile) => {
// // Check the video resolution first
// const { height } = await getVideoMetadata(videoFile);
// if (height {
console.log("Starting video conversion...");

// Check the video resolution first
const { height } = await getVideoMetadata(videoFile);
console.log(`Video height: ${height}`);

if (height 50 * 1024 * 1024) { // 50MB limit
console.error("File is too large for FFmpeg WebAssembly!");
message.error("File too large. Try a smaller video.");
return;
}

console.log("Memory seems okay. Writing file to FFmpeg...");
const fileName = `video_${Date.now()}.mp4`; // Generate a unique name
console.log(`Using filename: ${fileName}`);

await ffmpeg.writeFile(fileName, fetchedFile);
console.log(`File successfully written to FFmpeg memory as ${fileName}.`);

await ffmpeg.exec(['-i', 'input.mp4', '-vf', 'scale=-1:720', 'output.mp4']);
console.log("Conversion completed. Reading output file...");

const data = await ffmpeg.readFile('output.mp4');
console.log("File read successful. Creating new File object.");

const videoBlob = new Blob([data.buffer], { type: 'video/mp4' });
const convertedFile = new File([videoBlob], 'output.mp4', { type: 'video/mp4' });

console.log(convertedFile, "converted video from convertVideoTo720p");

return convertedFile;
};

const onFinish = async (values) => {
// Ensure a video is selected
if (!videoFileRef.current) {
message.error("Please select a video file.");
return;
}

// Create FormData
const formData = new FormData();
if (imageFile) {
formData.append("image", imageFile);
}

try {
message.info("Processing video. Please wait...");

// Convert the video to 720p only if needed
const convertedVideo = await convertVideoTo720p(videoFileRef.current);
console.log(convertedVideo, 'convertedVideo from onFinish');

formData.append("media", videoFileRef.current);

formData.append("data", JSON.stringify(values));

// Upload manually to the backend
const response = await createWorkoutVideo(formData).unwrap();
console.log(response, 'response from add video');

message.success("Video added successfully!");
form.resetFields(); // Reset form
setVideoFile(null); // Clear file

} catch (error) {
message.error(error.data?.message || "Failed to add video.");
}

// if (videoFile) {
// message.info("Processing video. Please wait...");
// try {
// // Convert the video to 720p only if needed
// const convertedVideo = await convertVideoTo720p(videoFile);
// formData.append("media", convertedVideo);
// } catch (conversionError) {
// message.error("Video conversion failed.");
// return;
// }
// }
// formData.append("data", JSON.stringify(values)); // Convert text fields to JSON

// try {
// const response = await createWorkoutVideo(formData).unwrap();
// console.log(response, 'response from add video');

// message.success("Video added successfully!");
// form.resetFields(); // Reset form
// setFile(null); // Clear file
// } catch (error) {
// message.error(error.data?.message || "Failed to add video.");
// }
};

const handleBackButtonClick = () => {
navigate(-1); // This takes the user back to the previous page
};

const videoUploadProps = {
name: 'video',
// action: 'https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload',
// headers: {
// authorization: 'authorization-text',
// },
// beforeUpload: (file) => {
// const isVideo = file.type.startsWith('video/');
// if (!isVideo) {
// message.error('You can only upload video files!');
// }
// return isVideo;
// },
// onChange(info) {
// if (info.file.status === 'done') {
// message.success(`${info.file.name} video uploaded successfully`);
// } else if (info.file.status === 'error') {
// message.error(`${info.file.name} video upload failed.`);
// }
// },
beforeUpload: (file) => {
const isVideo = file.type.startsWith('video/');
if (!isVideo) {
message.error('You can only upload video files!');
return Upload.LIST_IGNORE; // Prevents the file from being added to the list
}
videoFileRef.current = file; // Store file in ref
// setVideoFile(file); // Store the file in state instead of uploading it automatically
return false; // Prevent auto-upload
},
};

const imageUploadProps = {
name: 'image',
action: 'https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload',
headers: {
authorization: 'authorization-text',
},
beforeUpload: (file) => {
const isImage = file.type.startsWith('image/');
if (!isImage) {
message.error('You can only upload image files!');
}
return isImage;
},
onChange(info) {
if (info.file.status === 'done') {
message.success(`${info.file.name} image uploaded successfully`);
} else if (info.file.status === 'error') {
message.error(`${info.file.name} image upload failed.`);
}
},
};
return (



Add Video



Adding Video



{/* Section 1 */}
{/* */}
{/* */}




{/* Video */}



Select a video





{/* Thumbnail */}



Select an image





{/* Title */}







{/* */}
{/* */}

{/* Submit Button */}



{isLoading ? 'Uploading...' : 'Upload'}








)
}

export default AddWorkoutVideo< /code>
< /div>
< /div>
< /p>
оценил бы любые идеи или предложения. Спасибо!


Подробнее здесь: https://stackoverflow.com/questions/794 ... ant-design
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Javascript»