
Recherche avancée
Médias (91)
-
Valkaama DVD Cover Outside
4 octobre 2011, par
Mis à jour : Octobre 2011
Langue : English
Type : Image
-
Valkaama DVD Label
4 octobre 2011, par
Mis à jour : Février 2013
Langue : English
Type : Image
-
Valkaama DVD Cover Inside
4 octobre 2011, par
Mis à jour : Octobre 2011
Langue : English
Type : Image
-
1,000,000
27 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
-
Demon Seed
26 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
-
The Four of Us are Dying
26 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
Autres articles (67)
-
Gestion des droits de création et d’édition des objets
8 février 2011, parPar défaut, beaucoup de fonctionnalités sont limitées aux administrateurs mais restent configurables indépendamment pour modifier leur statut minimal d’utilisation notamment : la rédaction de contenus sur le site modifiables dans la gestion des templates de formulaires ; l’ajout de notes aux articles ; l’ajout de légendes et d’annotations sur les images ;
-
Dépôt de média et thèmes par FTP
31 mai 2013, parL’outil MédiaSPIP traite aussi les média transférés par la voie FTP. Si vous préférez déposer par cette voie, récupérez les identifiants d’accès vers votre site MédiaSPIP et utilisez votre client FTP favori.
Vous trouverez dès le départ les dossiers suivants dans votre espace FTP : config/ : dossier de configuration du site IMG/ : dossier des média déjà traités et en ligne sur le site local/ : répertoire cache du site web themes/ : les thèmes ou les feuilles de style personnalisées tmp/ : dossier de travail (...) -
Keeping control of your media in your hands
13 avril 2011, parThe 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 (...)
Sur d’autres sites (9540)
-
How to setup my complex filter with zoompan and xfade for ffmpeg using Fluent-FFmpeg .complexFilter method ?
20 août 2024, par Rémy Groleaui'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]
toinputs: [
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 LukeProblem :


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 :


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


Lambda Function Code :


async function concat(bucketName, imageKeys) {
 const imageStreams = await Promise.all(
 imageKeys.map(async (key, i) => {
 const command = new GetObjectCommand({ Bucket: bucketName, Key: key });
 const response = await s3.send(command);
 // Define the temporary file path based on the index
 const tempFilePath = `/tmp/${i}.png`;
 
 // Write the image data to the temporary file
 await fs.writeFile(tempFilePath, response.Body);
 
 // Return the file path to be used later
 return tempFilePath;
 })
 );
 
 // Create a file list content with durations
 let fileContent = "";
 for (let i = 0; i < imageStreams.length; i++) {
 fileContent += `file '${imageStreams[i]}'\nduration 1\n`;
 
 // Check if it's the last image, and if so, add it again
 if (i === imageStreams.length - 1) {
 fileContent += `file '${imageStreams[i]}'\nduration 1\n`;
 }
 }
 
 // Define the file path for the file list
 const fileListPath = "/tmp/file_list.txt";
 
 // Write the file list content to the file
 await fs.writeFile(fileListPath, fileContent);
 
 try {
 await fs.writeFile(fileListPath, fileContent);
 } catch (error) {
 console.error("Error writing file list:", error);
 throw error;
 }
 
 // Create a complex filter to add zooms and pans
 // Simplified filter example
 let complexFilter = [
 // Example of a fade transition
 {
 filter: 'fade',
 options: { type: 'in', start_time: 0, duration: 1 },
 inputs: '0:v', // first video stream
 outputs: 'fade0'
 },
 // Example of dynamic zoompan
 {
 filter: 'zoompan',
 options: {
 z: 'zoom+0.002',
 d: 120, // duration for this image
 x: 'if(gte(zoom,1.2),x,x+1)', // dynamic x position
 y: 'if(gte(zoom,1.2),y,y+1)' // dynamic y position
 },
 inputs: 'fade0',
 outputs: 'zoom0'
 }
 // Continue adding filters for each image
 ];

 let filterString = complexFilter
 .map(
 (f) =>
 `${f.filter}=${Object.entries(f.options)
 .map(([key, value]) => `${key}=${value}`)
 .join(":")}`
 )
 .join(",");
 
 let filterString = complexFilter
 .map(
 (f) =>
 `${f.filter}=${Object.entries(f.options)
 .map(([key, value]) => `${key}=${value}`)
 .join(":")}`
 )
 .join(",");
 
 console.log("Filter String:", filterString);
 
 return new Promise((resolve, reject) => {
 ffmpeg()
 .input(fileListPath)
 .complexFilter(filterString)
 .inputOptions(["-f concat", "-safe 0"])
 .outputOptions("-c copy")
 .outputOptions("-c:v libx264")
 .outputOptions("-pix_fmt yuv420p")
 .outputOptions("-r 30")
 .on("end", () => {
 resolve();
 })
 .on("error", (err) => {
 console.error("Error during video concatenation:", err);
 reject(err);
 })
 .saveToFile("/tmp/output.mp4");
 });
 }



Filter String Console Log :


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



Questions :


- 

- What is the correct syntax for implementing complex filters like zoompan and fade in ffmpeg when used in a Node.js environment ?
- How do I ensure the filters are applied correctly to each image in the sequence ?
- Is there a better way to dynamically generate these filters based on the number of images or their content ?








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


-
GLtransition not working properly with 480p
13 juin 2019, par Yukesh AravindI 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