Recherche avancée

Médias (1)

Mot : - Tags -/Rennes

Autres articles (95)

  • MediaSPIP 0.1 Beta version

    25 avril 2011, par

    MediaSPIP 0.1 beta is the first version of MediaSPIP proclaimed as "usable".
    The zip file provided here only contains the sources of MediaSPIP in its standalone version.
    To get a working installation, you must manually install all-software dependencies on the server.
    If you want to use this archive for an installation in "farm mode", you will also need to proceed to other manual (...)

  • Multilang : améliorer l’interface pour les blocs multilingues

    18 février 2011, par

    Multilang est un plugin supplémentaire qui n’est pas activé par défaut lors de l’initialisation de MediaSPIP.
    Après son activation, une préconfiguration est mise en place automatiquement par MediaSPIP init permettant à la nouvelle fonctionnalité d’être automatiquement opérationnelle. Il n’est donc pas obligatoire de passer par une étape de configuration pour cela.

  • Participer à sa traduction

    10 avril 2011

    Vous pouvez nous aider à améliorer les locutions utilisées dans le logiciel ou à traduire celui-ci dans n’importe qu’elle nouvelle langue permettant sa diffusion à de nouvelles communautés linguistiques.
    Pour ce faire, on utilise l’interface de traduction de SPIP où l’ensemble des modules de langue de MediaSPIP sont à disposition. ll vous suffit de vous inscrire sur la liste de discussion des traducteurs pour demander plus d’informations.
    Actuellement MediaSPIP n’est disponible qu’en français et (...)

Sur d’autres sites (6444)

  • How to setup my complex filter with zoompan and xfade for ffmpeg using Fluent-FFmpeg .complexFilter method ?

    20 août 2024, par Rémy Groleau

    i'm using fluent-ffmpeg with nodejs. My problem is the setup of my complex filter.

    


    const filters = Array.from({ length: imageCount - 1 }).map((_, i) => {
        const rndInt = Math.floor(Math.random() * 1000) + 1

        return {
            zoompanFilter1: {
                filter: 'zoompan',
                options: {
                    z: 'min(zoom+0.001,1.3)',
                    d: `${imageDuration * 60}`, 
                    x: `iw/2-iw*(1/2-${rndInt}/100)*iw/zoom`, 
                    y: `ih/2-ih*(1/2-${rndInt}/100)*ih/zoom`, 
                    s: '1080x1920', // Output size
                    fps: '60'
                },
                inputs: `[${i}:v]`,
                outputs: `zoomed${i}`
            },
            zoompanFilter2: {
                filter: 'zoompan',
                options: {
                    z: 'min(zoom+0.001,1.3)', 
                    d: `${imageDuration * 60}`, 
                    x: 'iw/2-iw*(1/2-33/100)*iw/zoom',
                    y: 'ih/2-ih*(1/2-33/100)*ih/zoom',
                    s: '1080x1920', // Output size
                    fps: '60'
                },
                inputs: [`${i + 1}:v`],
                outputs: `zoomed${i + 1}`
            },
            xfadeFilter: {
                filter: 'xfade',
                options: {
                    transition: 'fade', // Crossfade transition effect
                    duration: '0.5', // Duration of crossfade in seconds
                    offset: `${imageDuration - 1}` // Offset to start the crossfade
                },
                inputs: [`zoomed${i + 1}`, `zoomed${i}`],
                outputs: `crossfaded${i}`
            },
        };
    });


    


    This is my complete code :

    


    async function createVideo() {
    // Escape file paths for Windows
    const videoPath = path.resolve(__dirname+ '/output.mp4').replace(/\\/g, '\\\\');
    const audioPath = path.resolve(__dirname+ '/output.mp3').replace(/\\/g, '\\\\');
    const backgroundMusicPath = path.resolve(__dirname+ '/background-music.mp3').replace(/\\/g, '\\\\');

    const command = ffmpeg();

    const imagesDir = path.join(__dirname, 'images');
    const images = fs.readdirSync(imagesDir)
        .filter(file => /.(jpg|jpeg|png)$/i.test(file)) // Filter image files
        .sort() // Sort filenames to ensure the correct order
        .map(file => path.join(imagesDir, file));

        images.map((image) => command.input(image))

    const imageCount = images.length;
    const audioDuration = await getAudioDurationInSeconds(audioPath);
    const imageDuration =  Math.round(audioDuration / imageCount)

    const filters = Array.from({ length: imageCount - 1 }).map((_, i) => {
        const rndInt = Math.floor(Math.random() * 1000) + 1

        return {
            zoompanFilter1: {
                filter: 'zoompan',
                options: {
                    z: 'min(zoom+0.001,1.3)', // Reset zoom to 1.0
                    d: `${imageDuration * 60}`, // Duration of the zoom effect
                    x: `iw/2-iw*(1/2-${rndInt}/100)*iw/zoom`, // Center x
                    y: `ih/2-ih*(1/2-${rndInt}/100)*ih/zoom`, // Center y
                    s: '1080x1920', // Output size
                    fps: '60'
                },
                inputs: `[${i}:v]`,
                outputs: `zoomed${i}`
            },
            zoompanFilter2: {
                filter: 'zoompan',
                options: {
                    z: 'min(zoom+0.001,1.3)', // Reset zoom to 1.0
                    d: `${imageDuration * 60}`, // Duration of the zoom effect
                    x: 'iw/2-iw*(1/2-33/100)*iw/zoom', // Center x
                    y: 'ih/2-ih*(1/2-33/100)*ih/zoom', // Center y
                    s: '1080x1920', // Output size
                    fps: '60'
                },
                inputs: [`${i + 1}:v`],
                outputs: `zoomed${i + 1}`
            },
            xfadeFilter: {
                filter: 'xfade',
                options: {
                    transition: 'fade', // Crossfade transition effect
                    duration: '0.5', // Duration of crossfade in seconds
                    offset: `${imageDuration - 1}` // Offset to start the crossfade
                },
                inputs: [`zoomed${i + 1}`, `zoomed${i}`],
                outputs: `crossfaded${i}`
            },
        };
    });

    command
    .input(audioPath)
    .input(backgroundMusicPath)
    .outputOptions([
        '-pix_fmt', 'yuv420p',
        '-c:v', 'libx264',
        '-c:a', 'aac',
        '-y',
        '-t', `${audioDuration}`,
        '-r', '60',
        '-s', '1080x1920',
        '-preset', 'ultrafast',
        '-map', '[final_video]',
        '-map', '[mixed_audio]',
    ])
    .complexFilter([
        // Apply zoompan filters and xfade transitions
        ...filters.flatMap(({ zoompanFilter1, zoompanFilter2, xfadeFilter }) => [
            zoompanFilter1,
            zoompanFilter2,
            xfadeFilter,
        ]),
        {
            filter: 'concat',
            options: {
                n: imageCount - 1, // Number of videos to concatenate
                v: 1, // Video streams
                a: 0 // No audio streams
            },
            inputs: filters.map((_, i) => `crossfaded${i}`),
            outputs: 'video_sequence'
        },
        {
            filter: 'curves',
            options: 'preset=increase_contrast',
            inputs: 'video_sequence',
            outputs: 'curves'
        },
        {
            filter: 'subtitles',
            options: `./subtitles.ass:fontsdir=./fonts/:force_style='FontName=Montserrat Black Italic,FontSize=17,MarginL=10,MarginV=25,Alignment=10,Spacing=0.2,Outline=0.1,Shadow=1.5'`,
            inputs: '[curves]',
            outputs: 'final_video'
        },
        {
            filter: 'volume',
            options: 0.3,  // Adjust the volume to 25% of the original
            inputs: `${imageCount + 1}:a`,
            outputs: 'background_music_adjusted'
        },
        // Apply the amix filter to mix the two audio inputs
        {
            filter: 'amix',
            options: {
                inputs: 2,
                duration: 'first',
                dropout_transition: 0,
                weights: '1 0.25',
                normalize: 0
            },
            inputs: [`${imageCount}:a`, 'background_music_adjusted'],
            outputs: 'mixed_audio'
        },
      ])
    .save(videoPath)
    .on('progress', function(progress) {
        console.log('Processing: ' + progress.percent + '% done');
      })
    .on('end', function(stdout, stderr) {
        // emptyFolder(imagesDir)
        console.log('Transcoding succeeded !');
      }) 
    .on('error', function(err) {
        console.error('Une erreur s\'est produite :', err.message);
    });
}


    


    My problem is i see the 1 image then the transition and i see the 2 image. After that i'm suppose to see the 3 image but i see the 2 image.

    


    I don't understand what i'm doing wrong...

    


    i tried switching the inputs: [zoomed$i + 1, zoomed$i] to inputs: [zoomed$i, zoomed$i+1] but it just showed the next image and not a loop of consecutive images.

    


  • How to Correctly Implement ffmpeg Complex Filters in Node.js for Image Processing ?

    24 janvier 2024, par Luke

    Problem :

    


    I am trying to add filters and transitions between my image slideshow array, and am struggling to apply the proper filters. For example, I get errors like this :

    


    {&#xA;  "errorType": "Error",&#xA;  "errorMessage": "ffmpeg exited with code 234: Failed to set value &#x27;fade=type=in:start_time=0:duration=1,zoompan=z=zoom&#x2B;0.002:d=120:x=if(gte(zoom,1.2),x,x&#x2B;1):y=if(gte(zoom,1.2),y,y&#x2B;1)&#x27; for option &#x27;filter_complex&#x27;: Invalid argument\nError parsing global options: Invalid argument\n",&#xA;  "trace": [&#xA;    "Error: ffmpeg exited with code 234: Failed to set value &#x27;fade=type=in:start_time=0:duration=1,zoompan=z=zoom&#x2B;0.002:d=120:x=if(gte(zoom,1.2),x,x&#x2B;1):y=if(gte(zoom,1.2),y,y&#x2B;1)&#x27; for option &#x27;filter_complex&#x27;: Invalid argument",&#xA;    "Error parsing global options: Invalid argument",&#xA;    "",&#xA;    "    at ChildProcess.<anonymous> (/opt/nodejs/node_modules/fluent-ffmpeg/lib/processor.js:182:22)",&#xA;    "    at ChildProcess.emit (node:events:517:28)",&#xA;    "    at ChildProcess._handle.onexit (node:internal/child_process:292:12)"&#xA;  ]&#xA;}&#xA;</anonymous>

    &#xA;

    Lambda Function Code :

    &#xA;

     async function concat(bucketName, imageKeys) {&#xA;      const imageStreams = await Promise.all(&#xA;        imageKeys.map(async (key, i) => {&#xA;          const command = new GetObjectCommand({ Bucket: bucketName, Key: key });&#xA;          const response = await s3.send(command);&#xA;          // Define the temporary file path based on the index&#xA;          const tempFilePath = `/tmp/${i}.png`;&#xA;    &#xA;          // Write the image data to the temporary file&#xA;          await fs.writeFile(tempFilePath, response.Body);&#xA;    &#xA;          // Return the file path to be used later&#xA;          return tempFilePath;&#xA;        })&#xA;      );&#xA;    &#xA;      // Create a file list content with durations&#xA;      let fileContent = "";&#xA;      for (let i = 0; i &lt; imageStreams.length; i&#x2B;&#x2B;) {&#xA;        fileContent &#x2B;= `file &#x27;${imageStreams[i]}&#x27;\nduration 1\n`;&#xA;    &#xA;        // Check if it&#x27;s the last image, and if so, add it again&#xA;        if (i === imageStreams.length - 1) {&#xA;          fileContent &#x2B;= `file &#x27;${imageStreams[i]}&#x27;\nduration 1\n`;&#xA;        }&#xA;      }&#xA;    &#xA;      // Define the file path for the file list&#xA;      const fileListPath = "/tmp/file_list.txt";&#xA;    &#xA;      // Write the file list content to the file&#xA;      await fs.writeFile(fileListPath, fileContent);&#xA;    &#xA;      try {&#xA;        await fs.writeFile(fileListPath, fileContent);&#xA;      } catch (error) {&#xA;        console.error("Error writing file list:", error);&#xA;        throw error;&#xA;      }&#xA;    &#xA;      // Create a complex filter to add zooms and pans&#xA;      // Simplified filter example&#xA;  let complexFilter = [&#xA;    // Example of a fade transition&#xA;    {&#xA;      filter: &#x27;fade&#x27;,&#xA;      options: { type: &#x27;in&#x27;, start_time: 0, duration: 1 },&#xA;      inputs: &#x27;0:v&#x27;, // first video stream&#xA;      outputs: &#x27;fade0&#x27;&#xA;    },&#xA;    // Example of dynamic zoompan&#xA;    {&#xA;      filter: &#x27;zoompan&#x27;,&#xA;      options: {&#xA;        z: &#x27;zoom&#x2B;0.002&#x27;,&#xA;        d: 120, // duration for this image&#xA;        x: &#x27;if(gte(zoom,1.2),x,x&#x2B;1)&#x27;, // dynamic x position&#xA;        y: &#x27;if(gte(zoom,1.2),y,y&#x2B;1)&#x27; // dynamic y position&#xA;      },&#xA;      inputs: &#x27;fade0&#x27;,&#xA;      outputs: &#x27;zoom0&#x27;&#xA;    }&#xA;    // Continue adding filters for each image&#xA;  ];&#xA;&#xA;  let filterString = complexFilter&#xA;    .map(&#xA;      (f) =>&#xA;        `${f.filter}=${Object.entries(f.options)&#xA;          .map(([key, value]) => `${key}=${value}`)&#xA;          .join(":")}`&#xA;    )&#xA;    .join(",");&#xA;    &#xA;      let filterString = complexFilter&#xA;        .map(&#xA;          (f) =>&#xA;            `${f.filter}=${Object.entries(f.options)&#xA;              .map(([key, value]) => `${key}=${value}`)&#xA;              .join(":")}`&#xA;        )&#xA;        .join(",");&#xA;    &#xA;      console.log("Filter String:", filterString);&#xA;    &#xA;      return new Promise((resolve, reject) => {&#xA;        ffmpeg()&#xA;          .input(fileListPath)&#xA;          .complexFilter(filterString)&#xA;          .inputOptions(["-f concat", "-safe 0"])&#xA;          .outputOptions("-c copy")&#xA;          .outputOptions("-c:v libx264")&#xA;          .outputOptions("-pix_fmt yuv420p")&#xA;          .outputOptions("-r 30")&#xA;          .on("end", () => {&#xA;            resolve();&#xA;          })&#xA;          .on("error", (err) => {&#xA;            console.error("Error during video concatenation:", err);&#xA;            reject(err);&#xA;          })&#xA;          .saveToFile("/tmp/output.mp4");&#xA;      });&#xA;    }&#xA;

    &#xA;

    Filter String Console Log :

    &#xA;

    Filter String: fade=type=in:start_time=0:duration=1,zoompan=z=zoom&#x2B;0.002:d=120:x=if(gte(zoom,1.2),x,x&#x2B;1):y=if(gte(zoom,1.2),y,y&#x2B;1)&#xA;

    &#xA;

    Questions :

    &#xA;

      &#xA;
    1. What is the correct syntax for implementing complex filters like zoompan and fade in ffmpeg when used in a Node.js environment ?
    2. &#xA;

    3. How do I ensure the filters are applied correctly to each image in the sequence ?
    4. &#xA;

    5. Is there a better way to dynamically generate these filters based on the number of images or their content ?
    6. &#xA;

    &#xA;

    Any insights or examples of correctly implementing this would be greatly appreciated !

    &#xA;

  • GLtransition not working properly with 480p

    13 juin 2019, par Yukesh Aravind

    I have a problem with GL Transition while rendering video at 480p, GL EFFECT applies but not as it was but it works fine for 1080P and 720P, here is my command :

    ffmpeg -y -loop 1 -t 5 -i /srv/sample/text_images/textimage_bRq4E_1560330312.png -loop 1 -t 8 -i /srv/sample/text_images/textimage_mZPFr_1560330318.png -loop 1 -t 16 -i 'https://pixabay.com/get/52e3d14a4b5ab114a6df8c7ece2a3e7f083edbe35352704f742779.jpg' -loop 1 -t 18 -i 'https://pixabay.com/get/55e6d7424f52b114a6df8c7ece2a3e7f083edbe35352704f742779.jpg' -t 8 -i '/srv/sample/img/image.png' -filter_complex "[2:v]scale=w=2556:h=1440,zoompan=z='zoom+0.001':x='if(gte(zoom,1.5),x,x-1)':y='y':s=852x480:d=180,setsar=1,drawbox=color=black@0:width=iw:height=ih:t=fill[v2];[v2][0:v]overlay=x=(main_w-overlay_w)/2:y=(main_h-overlay_h)/2[v2];[4:v]fps=25,scale=25:25,setsar=1:1[v4];[v2][v4]overlay=x=10:y=(main_h-overlay_h)-10[v2];[3:v]scale=w=2556:h=1440,zoompan=z='zoom+0.001':x='if(gte(zoom,1.5),x,x-1)':y='y':s=852x480:d=240,setsar=1,drawsamplev/sample/fonts/Catamaran/Catamaran-Regular.ttf:text=pixabay.com:fontcolor=white:fontsize=20:x=60:y=(h-text_h)-10,drawbox=color=black@0:width=iw:height=ih:t=fill[v3];[v3][1:v]overlay=x=(main_w-overlay_w)/2:y=(main_h-overlay_h)/2[v3];[4:v]fps=25,scale=25:25,setsar=1:1[v4];[v3][v4]overlay=x=10:y=(main_h-overlay_h)-10[v3];[v2]split[s12][s22];[s12]trim=0:5:start=0:duration=5[s12];[s12]setpts=PTS-STARTPTS[s12];[s22]trim=5:6[s22];[s22]setpts=PTS-STARTPTS[s22];[v3]split[s13][s23];[s13]trim=0:7:start=0:duration=7[s13];[s13]setpts=PTS-STARTPTS[s13];[s23]trim=7:8[s23];[s23]setpts=PTS-STARTPTS[s23];[s22][s13]gltransition=duration=1:source=/filters/CircleCrop.glsl[vt0];[s12][vt0][s23]concat=n=3:v=1:a=0[tmp]" -map '[tmp]' -pix_fmt yuvj444p /srv/sample/rendered/video_h5DjO_1560330312.mp4

    what makes to fail, please let me to understand.

    I also attach the image, please give me some suggestions

    enter image description here