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.

  • Amélioration de la version de base

    13 septembre 2013

    Jolie sélection multiple
    Le plugin Chosen permet d’améliorer l’ergonomie des champs de sélection multiple. Voir les deux images suivantes pour comparer.
    Il suffit pour cela d’activer le plugin Chosen (Configuration générale du site > Gestion des plugins), puis de configurer le plugin (Les squelettes > Chosen) en activant l’utilisation de Chosen dans le site public et en spécifiant les éléments de formulaires à améliorer, par exemple select[multiple] pour les listes à sélection multiple (...)

  • Emballe médias : à quoi cela sert ?

    4 février 2011, par

    Ce plugin vise à gérer des sites de mise en ligne de documents de tous types.
    Il crée des "médias", à savoir : un "média" est un article au sens SPIP créé automatiquement lors du téléversement d’un document qu’il soit audio, vidéo, image ou textuel ; un seul document ne peut être lié à un article dit "média" ;

Sur d’autres sites (5058)

  • doc : clarify option on looping infinitely in movie filter

    2 février 2017, par Werner Robitza
    doc : clarify option on looping infinitely in movie filter
    

    Clarify that setting loop=0 is required to make the stream loop infinitely, rather than saying that a value "less than 1" is needed.

    Signed-off-by : Lou Logan <lou@lrcd.com>

    • [DH] doc/filters.texi
  • 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;

  • Ffmpeg cannot use the text having white space, while adding a text over a video

    13 août 2018, par Shubham Kamlapuri

    I am using ffmpeg to add text over a video, the text can be more than one also. The problem i am facing is with the text having white spaces, ffmpeg is showing the invalid argument.

    My command is like this :-

    ffmpeg -i input -filter_complex drawtext=fontfile=fontpath:fontcolor=0x000000ff:fontsize=121.26316137279886:shadowcolor=0xffffffff:shadowx=0:shadowy=0:bordercolor=0xffffffff:borderw=0:box=1:boxcolor=0x00000000:boxborderw=30:x=284.73258578742804:y=703.5501114572116:enable='between(t,0,9)':text='hello hello' -c:v libx264 -preset ultrafast output

    Error i am facing :

    ffmpeg : Unable to find a suitable output format for ’hello’’

    ffmpeg : hello’ : Invalid argument

    If i am entering text without spaces, it is working perfectly fine, but things are not good with text having spaces. I am stuck at this point from last 2 days, If anybody can help me, will be very helpful !