Recherche avancée

Médias (91)

Autres articles (57)

  • Websites made ​​with MediaSPIP

    2 mai 2011, par

    This page lists some websites based on MediaSPIP.

  • Keeping control of your media in your hands

    13 avril 2011, par

    The vocabulary used on this site and around MediaSPIP in general, aims to avoid reference to Web 2.0 and the companies that profit from media-sharing.
    While using MediaSPIP, you are invited to avoid using words like "Brand", "Cloud" and "Market".
    MediaSPIP is designed to facilitate the sharing of creative media online, while allowing authors to retain complete control of their work.
    MediaSPIP aims to be accessible to as many people as possible and development is based on expanding the (...)

  • L’espace de configuration de MediaSPIP

    29 novembre 2010, par

    L’espace de configuration de MediaSPIP est réservé aux administrateurs. Un lien de menu "administrer" est généralement affiché en haut de la page [1].
    Il permet de configurer finement votre site.
    La navigation de cet espace de configuration est divisé en trois parties : la configuration générale du site qui permet notamment de modifier : les informations principales concernant le site (...)

Sur d’autres sites (5380)

  • How to Increase Conversions With Form Analysis

    30 janvier 2024, par Erin

    Forms are one of the most important elements of your website. They are also one of the most difficult elements to analyse and improve. 

    Unlike a webpage, forms aren’t all that easy to analyse with standard web analytics tools. You need to learn how to conduct form analysis if you want to improve your forms’ conversion rates and increase revenue. 

    In this article, we’ll explain what form analysis is and why conducting a thorough form analysis is so important. 

    What is form analysis ?

    Form analysis is a process that measures the effectiveness of your forms. Form analysis uses several tools and techniques like a form analytics platform, heatmaps, and session recordings to collect user data and understand how visitors behave when filling in forms. 

    The goal is to improve the design and effectiveness of your forms, reducing abandonment rate and encouraging more users to submit them. 

    There are plenty of reasons visitors could be having trouble with your forms, from confusing form fields to poor design and lengthy verification processes. Form analytics can help you pinpoint why your form’s conversion rate is so low or why so many users abandon your form halfway through filling it in. 

    Why is form analysis important ?

    Website forms have some of the highest bounce rates and abandonments of any website element. By analysing your forms, you can achieve the following outcomes :

    Why is form analytics important?

    Reduce form abandonment

    When it’s tough enough to get users to start filling in your form, the last thing you want them to do is abandon it halfway through. But that’s probably what your users are doing more than you’d like to think. 

    Why are they abandoning it ? Even if you’re humble enough to admit you didn’t create the greatest form the world’s ever seen, it can still be incredibly difficult to pin down why users give up on your form.

    That’s unless you conduct a form analysis. By analysing metrics and user behaviour, you can pinpoint and rectify the issues that cause users to abandon your form. 

    Improve the user experience

    Best practices will only take you so far. How users behave when filling in a form on your website may be completely different to how they behave on another site. That’s why you need to use form analysis to understand how users behave specifically on your website — and then use that information to optimise the design, layout, and content of the form to better suit them. 

    If one field is regularly left empty, for example, you can delete it. If users spend several minutes filling out a form with a high abandonment rate, you could shorten it. 

    The goal isn’t to make the best form ever but to make the best form for your audience. 

    Increase conversions

    Ultimately, form analysis helps you improve your form’s most important metric : conversions. Reducing your abandonment rate will naturally lead to more completions, but so will taking advantage of other optimisation opportunities that only become clear with form analysis. This can include optimisations like :

    • Moving the form higher up on the page
    • Shortening the form
    • Changing the heading and CTAs
    • Renaming field labels 

    A thorough form analysis process can ensure your forms generate as many conversions as possible. 

    Why do users abandon forms ?

    Are you already suffering from high form abandonment rates ? Don’t worry, you’re not alone. Marketers regularly make the same mistakes when creating forms that cause users to give up halfway through completion.

    Here are some of the most common reasons for form abandonment :

    • There are too many steps. If you’re telling users they’ve just completed step 2 of 12, you can bet they won’t bother finishing your form. 
    • They ask for too much information. No one wants to fill out a long form, and often, users won’t have the information on hand if you ask for too much. Just look at the rate left blank from the Unneeded Fields report in the screenshot below :
    A screenshot showing fields left blank by users
    • The form is confusing. Unclear form fields or directions can put users off. 
    • All the fields are free text and time-consuming. Filling out forms with long text fields takes too much time. To speed things up, use dropdown options in the fields, but keep the options to a minimum. This not only helps users finish the form faster but also makes it easier to analyse the data later because it keeps the data format consistent so you can organise the information more efficiently. 
    • Users don’t trust the form. This is a particular problem on checkout pages where users are entering sensitive information.

    How to conduct form analysis

    You need to collect user behaviour data to effectively analyse your forms. But a lot of traditional website analytics tools won’t have the required functionality. 

    Matomo is different. Our web analytics solution offers comprehensive web analytics as well as additional features like Heatmaps, Session Recordings, A/B Testing, and Form Analytics to provide all the functionality you need. 

    Now if you don’t use Matomo, you can try it free for 21 days (no credit card required) to see if it’s the right tool for you.

    Whether you use Matomo or not is up to you. But, once you have a suitable tool in place, just follow the steps below to conduct a form analysis. 

    Check your analytics

    Tracking and analysing specific form metrics should be the first place you start. We recommend collecting data on the following metrics :

    • Form starter rate : the percentage of visitors who actually start to fill in your form
    • Completion rate : the percentage of visitors who complete the form
    • Form abandonment rate : the percentage of users who gave up filling in your form
    • Time spent completing your form : the average length of time users spend on your form

    Let’s look at these metrics are in Matomo’s Form Analytics :

    A screenshot of Matomo's form analytics dashboard

    The dashboard shows an overview of these metrics over a given period, allowing you to see at a glance whether there are issues you need to rectify. 

    Next, deep dive into the performance of each form to see things like :

    • Drop off fields
    • Unused fields
    • Entry field
    • Most corrected fields 

    You can even use Matomo’s visitor log to see who’s behind every submission.

    Try Matomo for Free

    Get the web insights you need, without compromising data accuracy.

    No credit card required

    Use a heatmap

    A heatmap is a colour-based graphical representation of data. A heatmap will show what users to do on your website, including : 

    • How far they scroll
    • Which buttons they click on
    • Where they focus their attention

    When used on a webpage with a form, you’ll be able to see how often users interact with your form based on the heatmap colour, with warmer colours representing greater engagement levels.

    Let’s look at a heatmap in Matomo :

    A screenshot of Matomo's heatmap feature

    This heatmap is showing us how far down users have scrolled. It’s clear that only 63% of visitors are reaching the point above our call to action to see all features. We might want to consider moving that call to action up in order to get more engagement. 

    A heatmap is a great way to see whether your form’s placement gets the level of attention you want from visitors and to what extent visitors interact with your field.

    Record user sessions

    Session replays go even further than heatmaps, recording a real-life user interacting with your site. It’s like looking over a visitor’s shoulder while they use your site.

    A screenshot of Matomo's heatmap feature

    With Matomo, you can record any sessions where the user takes a certain action (like starting to fill in a form), allowing you to build a rich library of qualitative data. 

    You can then replay a recorded session at your leisure to understand exactly how users interact with your forms.

    Segment users

    If you really want to understand how visitors use your forms, then it’s essential to segment your data. 

    You can segment all Form Analytics reports by over 100 pre-built segments in Matomo.

    A screenshot of Matomo's user segmentation feature

    One way to segment your data is by comparing the average time on form of those who completed the form with those who abandoned it. 

    If users abandon a form quickly, that could indicate your form is irrelevant to this audience or too long. If users spend a lot of time on the form, however, it’s probably safe to assume that it is relevant but there is something wrong with the form itself. 

    Looking at the Field Timings report will help you pinpoint which field visitors are spending the most time on and causing frustration. 

    Field Timings Report example in Matomo dashboard

    The Field Timings example report in Matomo above, it’s evident that the “Overview of your needs” field takes up the most time (avg. time spent is 1 min 40s). To improve this, we might want to change it to a dropdown field. This way, users can quickly select options, and if necessary, provide additional details.

    Try Matomo for Free

    Get the web insights you need, without compromising data accuracy.

    No credit card required

    Another way is to segment data by traffic source and compare each source’s conversion rate. This will show whether one traffic source converts better than another or if one source isn’t interested in your form at all.

    How to optimise web forms

    Want to implement what you’ve learnt from your form analysis ? Follow these steps to optimise your existing web forms. 

    Define your form’s purpose

    The first step in optimising your existing web forms is to give a clear and definitive purpose to every single one. 

    When you have a defined goal, creating a form users will complete is much easier. After all, if you don’t know why people should fill in one of your forms, how would a visitor possibly know ?

    Take a look at one of our forms below :

    A form on Matomo's website

    The purpose of this form is to get users to sign up for a free trial of our web analytics platform, and every element works towards that goal :

    • The headline directs the user to take action
    • The copy explains that it’s a free trial that doesn’t require credit card details
    • The green call-to-action button reinforces the action and benefit 
    • There is validation to support this under the form – “Trusted on over 1 million websites in over 190+ countries”

    Our clear instructions leave users no doubt about why they should fill in the form or what will happen. 

    Choose the right type of form

    You can use several forms on your website, each with different designs, form fields, and goals.

    For example :

    • Registration forms are fairly minimalist and designed to collect the least amount of data possible. 
    • Contact forms are concise so that it’s easy for potential customers to reach your team. 
    • Checkout forms balance a need to collect important data with a streamlined design that doesn’t put users off.
    • Lead generation forms are compelling and usually include qualifying questions so sales teams can score leads.

    Make sure you are using the right type of form to avoid abandonments and other issues. For example, requiring users to fill in a lengthy lead generation-style form when you want them to sign up for a free trial will probably kill your conversion rate. 

    Test form elements

    If your form analysis has shed light on one or two issues, you can use A/B or multivariate testing to trial new elements or designs and see how they compare.

    There’s no shortage of elements you can test, including the form’s :

    • Headline
    • Placement
    • Design
    • CTA button
    • Colour-scheme
    • Length
    • Form fields
    Matomo A/B Test feature

    Matomo makes it easy to create and run A/B tests on your website’s forms. 

    Move your form above the fold

    One of the simplest ways to optimise your web form is to move it above the fold — that’s the section of the screen users see when they load your page. 

    Why ? Well, the more people who see your form, the more people will fill it in. And when it’s above the fold, users can’t help but see it.

    Conclusion

    Forms are one of the most important elements on your website, so why not treat them as such and regularly run a thorough form analysis ? By doing so, you’ll identify ways to optimise your form, improve the user experience, and improve conversions. 

    Matomo is the best platform for conducting form analysis. Our combination of web analytics, Form Analytics, Session Recordings, and Heatmaps means you have all the tools you need to learn exactly how visitors interact with your forms. 

    See just how powerful Matomo’s tools are by starting a free 21-day trial, no credit card required. 

  • swscale : use 16-bit intermediate precision for RGB/XYZ conversion

    16 décembre 2024, par Niklas Haas
    swscale : use 16-bit intermediate precision for RGB/XYZ conversion
    

    The current logic uses 12-bit linear light math, which is woefully insufficient
    and leads to nasty postarization artifacts. This patch simply switches the
    internal logic to 16-bit precision.

    This raises the memory requirement of these tables from 32 kB to 272 kB.

    All relevant FATE tests updated for improved accuracy.

    Fixes : #4829
    Signed-off-by : Niklas Haas <git@haasn.dev>
    Sponsored-by : Sovereign Tech Fund

    • [DH] libswscale/swscale.c
    • [DH] libswscale/swscale_internal.h
    • [DH] libswscale/utils.c
    • [DH] tests/ref/fate/filter-pixdesc-xyz12be
    • [DH] tests/ref/fate/filter-pixdesc-xyz12le
    • [DH] tests/ref/fate/filter-pixfmts-copy
    • [DH] tests/ref/fate/filter-pixfmts-crop
    • [DH] tests/ref/fate/filter-pixfmts-field
    • [DH] tests/ref/fate/filter-pixfmts-fieldorder
    • [DH] tests/ref/fate/filter-pixfmts-hflip
    • [DH] tests/ref/fate/filter-pixfmts-il
    • [DH] tests/ref/fate/filter-pixfmts-null
    • [DH] tests/ref/fate/filter-pixfmts-scale
    • [DH] tests/ref/fate/filter-pixfmts-transpose
    • [DH] tests/ref/fate/filter-pixfmts-vflip
    • [DH] tests/ref/pixfmt/gbrp-xyz12le
    • [DH] tests/ref/pixfmt/gbrp10-xyz12le
    • [DH] tests/ref/pixfmt/gbrp12-xyz12le
    • [DH] tests/ref/pixfmt/rgb24-xyz12le
    • [DH] tests/ref/pixfmt/rgb48-xyz12le
    • [DH] tests/ref/pixfmt/xyz12le
    • [DH] tests/ref/pixfmt/yuv444p-xyz12le
    • [DH] tests/ref/pixfmt/yuv444p10-xyz12le
    • [DH] tests/ref/pixfmt/yuv444p12-xyz12le
  • 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;