Recherche avancée

Médias (91)

Autres articles (63)

  • Websites made ​​with MediaSPIP

    2 mai 2011, par

    This page lists some websites based on MediaSPIP.

  • Creating farms of unique websites

    13 avril 2011, par

    MediaSPIP platforms can be installed as a farm, with a single "core" hosted on a dedicated server and used by multiple websites.
    This allows (among other things) : implementation costs to be shared between several different projects / individuals rapid deployment of multiple unique sites creation of groups of like-minded sites, making it possible to browse media in a more controlled and selective environment than the major "open" (...)

  • Les autorisations surchargées par les plugins

    27 avril 2010, par

    Mediaspip core
    autoriser_auteur_modifier() afin que les visiteurs soient capables de modifier leurs informations sur la page d’auteurs

Sur d’autres sites (10540)

  • dcaenc : Implementation of Huffman codes for DCA encoder

    7 janvier 2017, par Daniil Cherednik
    dcaenc : Implementation of Huffman codes for DCA encoder
    

    Reviewed-by : Rostislav Pehlivanov <atomnuker@gmail.com>

    • [DH] libavcodec/Makefile
    • [DH] libavcodec/dca_core.c
    • [DH] libavcodec/dcadata.c
    • [DH] libavcodec/dcadata.h
    • [DH] libavcodec/dcaenc.c
    • [DH] libavcodec/dcaenc.h
    • [DH] libavcodec/dcahuff.c
    • [DH] libavcodec/dcahuff.h
    • [DH] tests/fate/acodec.mak
  • Revision 28930 : on bouge

    31 mai 2009, par ben.spip@… — Log

    on bouge

  • FFmpeg WASM writeFile Stalls and Doesn't Complete in React App with Ant Design

    26 février, par raiyan khan

    I'm using FFmpeg WebAssembly (WASM) in a React app to process and convert a video file before uploading it. The goal is to resize the video to 720p using FFmpeg before sending it to the backend.

    &#xA;

    Problem :

    &#xA;

    Everything works up to fetching the file and confirming it's loaded into memory, but FFmpeg hangs at ffmpeg.writeFile() and does not proceed further. No errors are thrown.

    &#xA;

    Code Snippet :

    &#xA;

      &#xA;
    • Loading FFmpeg

      &#xA;

       const loadFFmpeg = async () => {&#xA; if (loaded) return; // Avoid reloading if &#xA; already loaded&#xA;&#xA; const baseURL = &#x27;https://unpkg.com/@ffmpeg/core@0.12.6/dist/umd&#x27;;&#xA; const ffmpeg = ffmpegRef.current;&#xA; ffmpeg.on(&#x27;log&#x27;, ({ message }) => {&#xA;     messageRef.current.innerHTML = message;&#xA;     console.log(message);&#xA; });&#xA; await ffmpeg.load({&#xA;     coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, &#x27;text/javascript&#x27;),&#xA;     wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, &#x27;application/wasm&#x27;),&#xA; });&#xA; setLoaded(true);&#xA; };&#xA;&#xA; useEffect(() => {&#xA; loadFFmpeg()&#xA; }, [])&#xA;

      &#xA;

    • &#xA;

    • Fetching and Writing File

      &#xA;

        const convertVideoTo720p = async (videoFile) => {&#xA;       console.log("Starting video &#xA;     conversion...");&#xA;&#xA;&#xA;&#xA; const { height } = await getVideoMetadata(videoFile);&#xA; console.log(`Video height: ${height}`);&#xA;&#xA; if (height &lt;= 720) {&#xA;     console.log("No conversion needed.");&#xA;     return videoFile;&#xA; }&#xA;&#xA; const ffmpeg = ffmpegRef.current;&#xA; console.log("FFmpeg instance loaded. Writing file to memory...");&#xA;&#xA; const fetchedFile = await fetchFile(videoFile);&#xA; console.log("File fetched successfully:", fetchedFile);&#xA;&#xA; console.log("Checking FFmpeg memory before writing...");&#xA; console.log(`File size: ${fetchedFile.length} bytes (~${(fetchedFile.length / 1024 / 1024).toFixed(2)} MB)`);&#xA;&#xA; if (!ffmpeg.isLoaded()) {&#xA;     console.error("FFmpeg is not fully loaded yet!");&#xA;     return;&#xA; }&#xA;&#xA; console.log("Memory seems okay. Writing file to FFmpeg...");&#xA; await ffmpeg.writeFile(&#x27;input.mp4&#x27;, fetchedFile);  // ❌ This line hangs, nothing after runs&#xA; console.log("File successfully written to FFmpeg memory.");&#xA;      };&#xA;

      &#xA;

    • &#xA;

    &#xA;

    Debugging Steps I've Tried :

    &#xA;

      &#xA;
    • Ensured FFmpeg is fully loaded before calling writeFile()&#xA;✅ ffmpeg.isLoaded() returns true.
    • &#xA;

    • Checked file fetch process :&#xA;✅ fetchFile(videoFile) successfully returns a Uint8Array.
    • &#xA;

    • Tried renaming the file to prevent caching issues&#xA;✅ Used a unique file name like video_${Date.now()}.mp4, but no change
    • &#xA;

    • Checked browser console for errors :&#xA;❌ No errors are displayed.
    • &#xA;

    • Tried skipping FFmpeg and uploading the raw file instead :&#xA;✅ Upload works fine without FFmpeg, so the issue is specific to FFmpeg.
    • &#xA;

    &#xA;

    Expected Behavior

    &#xA;

      &#xA;
    • ffmpeg.writeFile(&#x27;input.mp4&#x27;, fetchedFile); should complete and allow FFmpeg to process the video.
    • &#xA;

    &#xA;

    Actual Behavior

    &#xA;

      &#xA;
    • Execution stops at writeFile, and no errors are thrown.
    • &#xA;

    &#xA;

    Environment :

    &#xA;

      &#xA;
    • React : 18.x
    • &#xA;

    • FFmpeg WASM Version : @ffmpeg/ffmpeg@0.12.15
    • &#xA;

    • Browser : Chrome 121, Edge 120
    • &#xA;

    • Operating System : Windows 11
    • &#xA;

    &#xA;

    Question :&#xA;Why is FFmpeg's writeFile() stalling and never completing ?&#xA;How can I fix or further debug this issue ?

    &#xA;

    Here is my full code :

    &#xA;

    &#xD;&#xA;
    &#xD;&#xA;
    import { useNavigate } from "react-router-dom";&#xA;import { useEffect, useRef, useState } from &#x27;react&#x27;;&#xA;import { Form, Input, Button, Select, Space } from &#x27;antd&#x27;;&#xA;const { Option } = Select;&#xA;import { FaAngleLeft } from "react-icons/fa6";&#xA;import { message, Upload } from &#x27;antd&#x27;;&#xA;import { CiCamera } from "react-icons/ci";&#xA;import { IoVideocamOutline } from "react-icons/io5";&#xA;import { useCreateWorkoutVideoMutation } from "../../../redux/features/workoutVideo/workoutVideoApi";&#xA;import { convertVideoTo720p } from "../../../utils/ffmpegHelper";&#xA;import { FFmpeg } from &#x27;@ffmpeg/ffmpeg&#x27;;&#xA;import { fetchFile, toBlobURL } from &#x27;@ffmpeg/util&#x27;;&#xA;&#xA;&#xA;const AddWorkoutVideo = () => {&#xA;    const [videoFile, setVideoFile] = useState(null);&#xA;    const [imageFile, setImageFile] = useState(null);&#xA;    const [loaded, setLoaded] = useState(false);&#xA;    const ffmpegRef = useRef(new FFmpeg());&#xA;    const videoRef = useRef(null);&#xA;    const messageRef = useRef(null);&#xA;    const [form] = Form.useForm();&#xA;    const [createWorkoutVideo, { isLoading }] = useCreateWorkoutVideoMutation()&#xA;    const navigate = useNavigate();&#xA;&#xA;    const videoFileRef = useRef(null); // Use a ref instead of state&#xA;&#xA;&#xA;    // Handle Video Upload&#xA;    const handleVideoChange = ({ file }) => {&#xA;        setVideoFile(file.originFileObj);&#xA;    };&#xA;&#xA;    // Handle Image Upload&#xA;    const handleImageChange = ({ file }) => {&#xA;        setImageFile(file.originFileObj);&#xA;    };&#xA;&#xA;    // Load FFmpeg core if needed (optional if you want to preload)&#xA;    const loadFFmpeg = async () => {&#xA;        if (loaded) return; // Avoid reloading if already loaded&#xA;&#xA;        const baseURL = &#x27;https://unpkg.com/@ffmpeg/core@0.12.6/dist/umd&#x27;;&#xA;        const ffmpeg = ffmpegRef.current;&#xA;        ffmpeg.on(&#x27;log&#x27;, ({ message }) => {&#xA;            messageRef.current.innerHTML = message;&#xA;            console.log(message);&#xA;        });&#xA;        await ffmpeg.load({&#xA;            coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, &#x27;text/javascript&#x27;),&#xA;            wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, &#x27;application/wasm&#x27;),&#xA;        });&#xA;        setLoaded(true);&#xA;    };&#xA;&#xA;    useEffect(() => {&#xA;        loadFFmpeg()&#xA;    }, [])&#xA;&#xA;    // Helper: Get video metadata (width and height)&#xA;    const getVideoMetadata = (file) => {&#xA;        return new Promise((resolve, reject) => {&#xA;            const video = document.createElement(&#x27;video&#x27;);&#xA;            video.preload = &#x27;metadata&#x27;;&#xA;            video.onloadedmetadata = () => {&#xA;                resolve({ width: video.videoWidth, height: video.videoHeight });&#xA;            };&#xA;            video.onerror = () => reject(new Error(&#x27;Could not load video metadata&#x27;));&#xA;            video.src = URL.createObjectURL(file);&#xA;        });&#xA;    };&#xA;&#xA;    // Inline conversion helper function&#xA;    // const convertVideoTo720p = async (videoFile) => {&#xA;    //     // Check the video resolution first&#xA;    //     const { height } = await getVideoMetadata(videoFile);&#xA;    //     if (height &lt;= 720) {&#xA;    //         // No conversion needed&#xA;    //         return videoFile;&#xA;    //     }&#xA;    //     const ffmpeg = ffmpegRef.current;&#xA;    //     // Load ffmpeg if not already loaded&#xA;    //     // await ffmpeg.load({&#xA;    //     //     coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, &#x27;text/javascript&#x27;),&#xA;    //     //     wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, &#x27;application/wasm&#x27;),&#xA;    //     // });&#xA;    //     // Write the input file to the ffmpeg virtual FS&#xA;    //     await ffmpeg.writeFile(&#x27;input.mp4&#x27;, await fetchFile(videoFile));&#xA;    //     // Convert video to 720p (scale filter maintains aspect ratio)&#xA;    //     await ffmpeg.exec([&#x27;-i&#x27;, &#x27;input.mp4&#x27;, &#x27;-vf&#x27;, &#x27;scale=-1:720&#x27;, &#x27;output.mp4&#x27;]);&#xA;    //     // Read the output file&#xA;    //     const data = await ffmpeg.readFile(&#x27;output.mp4&#x27;);&#xA;    //     console.log(data, &#x27;data from convertVideoTo720p&#x27;);&#xA;    //     const videoBlob = new Blob([data.buffer], { type: &#x27;video/mp4&#x27; });&#xA;    //     return new File([videoBlob], &#x27;output.mp4&#x27;, { type: &#x27;video/mp4&#x27; });&#xA;    // };&#xA;    const convertVideoTo720p = async (videoFile) => {&#xA;        console.log("Starting video conversion...");&#xA;&#xA;        // Check the video resolution first&#xA;        const { height } = await getVideoMetadata(videoFile);&#xA;        console.log(`Video height: ${height}`);&#xA;&#xA;        if (height &lt;= 720) {&#xA;            console.log("No conversion needed. Returning original file.");&#xA;            return videoFile;&#xA;        }&#xA;&#xA;        const ffmpeg = ffmpegRef.current;&#xA;        console.log("FFmpeg instance loaded. Writing file to memory...");&#xA;&#xA;        // await ffmpeg.writeFile(&#x27;input.mp4&#x27;, await fetchFile(videoFile));&#xA;        // console.log("File written. Starting conversion...");&#xA;        console.log("Fetching file for FFmpeg:", videoFile);&#xA;        const fetchedFile = await fetchFile(videoFile);&#xA;        console.log("File fetched successfully:", fetchedFile);&#xA;        console.log("Checking FFmpeg memory before writing...");&#xA;        console.log(`File size: ${fetchedFile.length} bytes (~${(fetchedFile.length / 1024 / 1024).toFixed(2)} MB)`);&#xA;&#xA;        if (fetchedFile.length > 50 * 1024 * 1024) { // 50MB limit&#xA;            console.error("File is too large for FFmpeg WebAssembly!");&#xA;            message.error("File too large. Try a smaller video.");&#xA;            return;&#xA;        }&#xA;&#xA;        console.log("Memory seems okay. Writing file to FFmpeg...");&#xA;        const fileName = `video_${Date.now()}.mp4`; // Generate a unique name&#xA;        console.log(`Using filename: ${fileName}`);&#xA;&#xA;        await ffmpeg.writeFile(fileName, fetchedFile);&#xA;        console.log(`File successfully written to FFmpeg memory as ${fileName}.`);&#xA;&#xA;        await ffmpeg.exec([&#x27;-i&#x27;, &#x27;input.mp4&#x27;, &#x27;-vf&#x27;, &#x27;scale=-1:720&#x27;, &#x27;output.mp4&#x27;]);&#xA;        console.log("Conversion completed. Reading output file...");&#xA;&#xA;        const data = await ffmpeg.readFile(&#x27;output.mp4&#x27;);&#xA;        console.log("File read successful. Creating new File object.");&#xA;&#xA;        const videoBlob = new Blob([data.buffer], { type: &#x27;video/mp4&#x27; });&#xA;        const convertedFile = new File([videoBlob], &#x27;output.mp4&#x27;, { type: &#x27;video/mp4&#x27; });&#xA;&#xA;        console.log(convertedFile, "converted video from convertVideoTo720p");&#xA;&#xA;        return convertedFile;&#xA;    };&#xA;&#xA;&#xA;    const onFinish = async (values) => {&#xA;        // Ensure a video is selected&#xA;        if (!videoFileRef.current) {&#xA;            message.error("Please select a video file.");&#xA;            return;&#xA;        }&#xA;&#xA;        // Create FormData&#xA;        const formData = new FormData();&#xA;        if (imageFile) {&#xA;            formData.append("image", imageFile);&#xA;        }&#xA;&#xA;        try {&#xA;            message.info("Processing video. Please wait...");&#xA;&#xA;            // Convert the video to 720p only if needed&#xA;            const convertedVideo = await convertVideoTo720p(videoFileRef.current);&#xA;            console.log(convertedVideo, &#x27;convertedVideo from onFinish&#x27;);&#xA;&#xA;            formData.append("media", videoFileRef.current);&#xA;&#xA;            formData.append("data", JSON.stringify(values));&#xA;&#xA;            // Upload manually to the backend&#xA;            const response = await createWorkoutVideo(formData).unwrap();&#xA;            console.log(response, &#x27;response from add video&#x27;);&#xA;&#xA;            message.success("Video added successfully!");&#xA;            form.resetFields(); // Reset form&#xA;            setVideoFile(null); // Clear file&#xA;&#xA;        } catch (error) {&#xA;            message.error(error.data?.message || "Failed to add video.");&#xA;        }&#xA;&#xA;        // if (videoFile) {&#xA;        //     message.info("Processing video. Please wait...");&#xA;        //     try {&#xA;        //         // Convert the video to 720p only if needed&#xA;        //         const convertedVideo = await convertVideoTo720p(videoFile);&#xA;        //         formData.append("media", convertedVideo);&#xA;        //     } catch (conversionError) {&#xA;        //         message.error("Video conversion failed.");&#xA;        //         return;&#xA;        //     }&#xA;        // }&#xA;        // formData.append("data", JSON.stringify(values)); // Convert text fields to JSON&#xA;&#xA;        // try {&#xA;        //     const response = await createWorkoutVideo(formData).unwrap();&#xA;        //     console.log(response, &#x27;response from add video&#x27;);&#xA;&#xA;        //     message.success("Video added successfully!");&#xA;        //     form.resetFields(); // Reset form&#xA;        //     setFile(null); // Clear file&#xA;        // } catch (error) {&#xA;        //     message.error(error.data?.message || "Failed to add video.");&#xA;        // }&#xA;    };&#xA;&#xA;    const handleBackButtonClick = () => {&#xA;        navigate(-1); // This takes the user back to the previous page&#xA;    };&#xA;&#xA;    const videoUploadProps = {&#xA;        name: &#x27;video&#x27;,&#xA;        // action: &#x27;https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload&#x27;,&#xA;        // headers: {&#xA;        //     authorization: &#x27;authorization-text&#x27;,&#xA;        // },&#xA;        // beforeUpload: (file) => {&#xA;        //     const isVideo = file.type.startsWith(&#x27;video/&#x27;);&#xA;        //     if (!isVideo) {&#xA;        //         message.error(&#x27;You can only upload video files!&#x27;);&#xA;        //     }&#xA;        //     return isVideo;&#xA;        // },&#xA;        // onChange(info) {&#xA;        //     if (info.file.status === &#x27;done&#x27;) {&#xA;        //         message.success(`${info.file.name} video uploaded successfully`);&#xA;        //     } else if (info.file.status === &#x27;error&#x27;) {&#xA;        //         message.error(`${info.file.name} video upload failed.`);&#xA;        //     }&#xA;        // },&#xA;        beforeUpload: (file) => {&#xA;            const isVideo = file.type.startsWith(&#x27;video/&#x27;);&#xA;            if (!isVideo) {&#xA;                message.error(&#x27;You can only upload video files!&#x27;);&#xA;                return Upload.LIST_IGNORE; // Prevents the file from being added to the list&#xA;            }&#xA;            videoFileRef.current = file; // Store file in ref&#xA;            // setVideoFile(file); // Store the file in state instead of uploading it automatically&#xA;            return false; // Prevent auto-upload&#xA;        },&#xA;    };&#xA;&#xA;    const imageUploadProps = {&#xA;        name: &#x27;image&#x27;,&#xA;        action: &#x27;https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload&#x27;,&#xA;        headers: {&#xA;            authorization: &#x27;authorization-text&#x27;,&#xA;        },&#xA;        beforeUpload: (file) => {&#xA;            const isImage = file.type.startsWith(&#x27;image/&#x27;);&#xA;            if (!isImage) {&#xA;                message.error(&#x27;You can only upload image files!&#x27;);&#xA;            }&#xA;            return isImage;&#xA;        },&#xA;        onChange(info) {&#xA;            if (info.file.status === &#x27;done&#x27;) {&#xA;                message.success(`${info.file.name} image uploaded successfully`);&#xA;            } else if (info.file.status === &#x27;error&#x27;) {&#xA;                message.error(`${info.file.name} image upload failed.`);&#xA;            }&#xA;        },&#xA;    };&#xA;    return (&#xA;        &lt;>&#xA;            <div classname="flex items-center gap-2 text-xl cursor-pointer">&#xA;                <faangleleft></faangleleft>&#xA;                <h1 classname="font-semibold">Add Video</h1>&#xA;            </div>&#xA;            <div classname="rounded-lg py-4 border-[#79CDFF] border-2 shadow-lg mt-8 bg-white">&#xA;                <div classname="space-y-[24px] min-h-[83vh] bg-light-gray rounded-2xl">&#xA;                    <h3 classname="text-2xl text-[#174C6B] mb-4 border-b border-[#79CDFF]/50 pb-3 pl-16 font-semibold">&#xA;                        Adding Video&#xA;                    </h3>&#xA;                    <div classname="w-full px-16">&#xA;                        / style={{ maxWidth: 600, margin: &#x27;0 auto&#x27; }}&#xA;                        >&#xA;                            {/* Section 1 */}&#xA;                            {/* <space direction="vertical" style="{{"> */}&#xA;                            {/* <space size="large" direction="horizontal" classname="responsive-space"> */}&#xA;                            <div classname="grid grid-cols-2 gap-8 mt-8">&#xA;                                <div>&#xA;                                    <space size="large" direction="horizontal" classname="responsive-space-section-2">&#xA;&#xA;                                        {/* Video */}&#xA;                                        Upload Video}&#xA;                                            name="media"&#xA;                                            className="responsive-form-item"&#xA;                                        // rules={[{ required: true, message: &#x27;Please enter the package amount!&#x27; }]}&#xA;                                        >&#xA;                                            <upload maxcount="{1}">&#xA;                                                <button style="{{" solid="solid">&#xA;                                                    <span style="{{" 600="600">Select a video</span>&#xA;                                                    <iovideocamoutline size="{20}" color="#174C6B"></iovideocamoutline>&#xA;                                                </button>&#xA;                                            </upload>&#xA;                                        &#xA;&#xA;                                        {/* Thumbnail */}&#xA;                                        Upload Image}&#xA;                                            name="image"&#xA;                                            className="responsive-form-item"&#xA;                                        // rules={[{ required: true, message: &#x27;Please enter the package amount!&#x27; }]}&#xA;                                        >&#xA;                                            <upload maxcount="{1}">&#xA;                                                <button style="{{" solid="solid">&#xA;                                                    <span style="{{" 600="600">Select an image</span>&#xA;                                                    <cicamera size="{25}" color="#174C6B"></cicamera>&#xA;                                                </button>&#xA;                                            </upload>&#xA;                                        &#xA;&#xA;                                        {/* Title */}&#xA;                                        Video Title}&#xA;                                            name="name"&#xA;                                            className="responsive-form-item-section-2"&#xA;                                        >&#xA;                                            <input type="text" placeholder="Enter video title" style="{{&amp;#xA;" solid="solid" />&#xA;                                        &#xA;                                    </space>&#xA;                                </div>&#xA;                            </div>&#xA;&#xA;                            {/* </space> */}&#xA;                            {/* </space> */}&#xA;&#xA;&#xA;                            {/* Submit Button */}&#xA;                            &#xA;                                <div classname="p-4 mt-10 text-center mx-auto flex items-center justify-center">&#xA;                                    &#xA;                                        <span classname="text-white font-semibold">{isLoading ? &#x27;Uploading...&#x27; : &#x27;Upload&#x27;}</span>&#xA;                                    &#xA;                                </div>&#xA;                            &#xA;                        &#xA;                    </div>&#xA;                </div>&#xA;            </div>&#xA;        >&#xA;    )&#xA;}&#xA;&#xA;export default AddWorkoutVideo

    &#xD;&#xA;

    &#xD;&#xA;

    &#xD;&#xA;&#xA;

    Would appreciate any insights or suggestions. Thanks !

    &#xA;