
Recherche avancée
Autres articles (80)
-
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 ;
-
Personnaliser en ajoutant son logo, sa bannière ou son image de fond
5 septembre 2013, parCertains thèmes prennent en compte trois éléments de personnalisation : l’ajout d’un logo ; l’ajout d’une bannière l’ajout d’une image de fond ;
-
Problèmes fréquents
10 mars 2010, parPHP et safe_mode activé
Une des principales sources de problèmes relève de la configuration de PHP et notamment de l’activation du safe_mode
La solution consiterait à soit désactiver le safe_mode soit placer le script dans un répertoire accessible par apache pour le site
Sur d’autres sites (4503)
-
avcodec/lossless_videoencdsp : Fix unaligned access
13 mars 2024, par Andreas Rheinhardtavcodec/lossless_videoencdsp : Fix unaligned access
HAVE_FAST_UNALIGNED being true does not imply that
one can simply read from any pointer via *(long*).
It is undefined behaviour in case the pointer is not
sufficiently aligned ; and even if it is, it is (likely)
a violation of the effective-type rules. Fix both
of these by using the appropriate AV_[RW]N macros.Also, the current code used sizeof(long) as if this
were the CPU's native arithmetic size, but this is
not true on 64bit Windows. This has been fixed, too.This affected huffyuv FATE-tests.
Tested-by : Sean McGovern <gseanmcg@gmail.com>
Signed-off-by : Andreas Rheinhardt <andreas.rheinhardt@outlook.com> -
Adding audio to video without re encoding [migrated]
4 mars 2015, par user1503606I am looking to add audio to a video without having to re encode the two pieces.
I have looked at a few questions on stack overflow followed the answers and i still cant seemed to get it to work, if anyone can spot what i am missing please help.
I am running this code.
ffmpeg -i DJ_Mes_Rescue-Some_Day-Guesthouse_Music.mp3 -i output.mp4 -map 0:0 -map 1:0 -acodec copy -vcodec copy -shortest edit2.mp4
Now from what i understand ffmpeg is mapping the stream over the top ffmpeg info for the audio track is.
Input #0, mp3, from 'DJ_Mes_Rescue-Some_Day-Guesthouse_Music.mp3':
Metadata:
encoder : LAME 64bits version 3.98.4 (http://www.mp3dev.org/)
title : Some Day
artist : DJ Mes, Rescue
TLEN : 378750
genre : House
track : 1/0
date : 2015
Duration: 00:06:18.80, start: 0.025056, bitrate: 320 kb/s
Stream #0:0: Audio: mp3, 44100 Hz, stereo, s16p, 320 kb/s
Metadata:
encoder : LAME3.98r
Side data:
replaygain: track gain - -10.100000, track peak - unknown, album gain - unknown, album peak - unknown,
Stream #0:1: Video: png, rgb24, 225x225, 90k tbr, 90k tbn, 90k tbc
Metadata:
title :
comment : OtherAnd for the video it is.
Input #1, mov,mp4,m4a,3gp,3g2,mj2, from 'output.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf56.15.102
Duration: 00:00:49.46, start: 0.046440, bitrate: 566 kb/s
Stream #1:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 568x320, 462 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
Metadata:
rotate : 90
handler_name : VideoHandler
Side data:
displaymatrix: rotation of -90.00 degrees
Stream #1:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 96 kb/s (default)
Metadata:
handler_name : SoundHandlerSo i am mapping the stream 0:0 from the audio file to 1:0 from the video file, but all i seem to get is a video with no audio.
Can someone help ?
UPDATE whole output added
ffmpeg -i Saison-Please_Don%27t_Go-Guesthouse_Music.mp3 -i output.mp4 -c copy -map 0:0 -map 1:0 -shortest mixed.mp4
ffmpeg version 2.5.2 Copyright (c) 2000-2014 the FFmpeg developers
built on Jan 12 2015 10:15:06 with Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
configuration: --prefix=/usr/local/Cellar/ffmpeg/2.5.2 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-libx264 --enable-libmp3lame --enable-libxvid --enable-libfreetype --enable-libtheora --enable-libvorbis --enable-libvpx --enable-librtmp --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libvo-aacenc --enable-libass --enable-ffplay --enable-libspeex --enable-libschroedinger --enable-libfdk-aac --enable-libopus --enable-frei0r --enable-libopenjpeg --disable-decoder=jpeg2000 --extra-cflags='-I/usr/local/Cellar/openjpeg/1.5.1_1/include/openjpeg-1.5 ' --enable-nonfree --enable-vda
libavutil 54. 15.100 / 54. 15.100
libavcodec 56. 13.100 / 56. 13.100
libavformat 56. 15.102 / 56. 15.102
libavdevice 56. 3.100 / 56. 3.100
libavfilter 5. 2.103 / 5. 2.103
libavresample 2. 1. 0 / 2. 1. 0
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 1.100 / 1. 1.100
libpostproc 53. 3.100 / 53. 3.100
Input #0, mp3, from 'Saison-Please_Don%27t_Go-Guesthouse_Music.mp3':
Metadata:
encoder : LAME 64bits version 3.98.4 (http://www.mp3dev.org/)
title : Please Donât Go
artist : Saison
TLEN : 408492
genre : House
track : 1/0
date : 2015
Duration: 00:06:48.53, start: 0.025056, bitrate: 320 kb/s
Stream #0:0: Audio: mp3, 44100 Hz, stereo, s16p, 320 kb/s
Metadata:
encoder : LAME3.98r
Side data:
replaygain: track gain - -8.400000, track peak - unknown, album gain - unknown, album peak - unknown,
Stream #0:1: Video: png, rgb24, 225x225, 90k tbr, 90k tbn, 90k tbc
Metadata:
title :
comment : Other
Input #1, mov,mp4,m4a,3gp,3g2,mj2, from 'output.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf56.15.102
Duration: 00:00:49.46, start: 0.046440, bitrate: 566 kb/s
Stream #1:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 568x320, 462 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
Metadata:
rotate : 90
handler_name : VideoHandler
Side data:
displaymatrix: rotation of -90.00 degrees
Stream #1:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 96 kb/s (default)
Metadata:
handler_name : SoundHandler
Output #0, mp4, to 'mixed.mp4':
Metadata:
date : 2015
title : Please Donât Go
artist : Saison
TLEN : 408492
genre : House
track : 1/0
encoder : Lavf56.15.102
Stream #0:0: Audio: mp3 (i[0][0][0] / 0x0069), 44100 Hz, stereo, 320 kb/s
Metadata:
encoder : LAME3.98r
Side data:
replaygain: track gain - -8.400000, track peak - unknown, album gain - unknown, album peak - unknown,
Stream #0:1(und): Video: h264 ([33][0][0][0] / 0x0021), yuv420p, 568x320, q=2-31, 462 kb/s, 30 fps, 15360 tbn, 15360 tbc (default)
Metadata:
rotate : 90
handler_name : VideoHandler
Side data:
displaymatrix: rotation of -90.00 degrees
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Stream #1:0 -> #0:1 (copy)
Press [q] to stop, [?] for help
frame= 1481 fps=0.0 q=-1.0 Lsize= 4759kB time=00:00:49.34 bitrate= 790.0kbits/s
video:2785kB audio:1929kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.960839%ANOTHER UPDATE :
So i have tried the following
ffmpeg -i 3.mp4 -i Saison-Please_Don%27t_Go-Guesthouse_Music.mp3 -i Saison-Please_Don%27t_Go-Guesthouse_Music.mp3 -map 0:0 -map 0:1 -map 1:0 -map 2:0 -c:v copy -c:a copy 23.mp4
and if i run.
ffmpeg -i 23.mp4
You can see the streams/audio has been added but it is not playing ?
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf56.15.102
Duration: 00:06:48.53, start: 0.025057, bitrate: 713 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 568x320, 462 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
Metadata:
rotate : 90
handler_name : VideoHandler
Side data:
displaymatrix: rotation of -90.00 degrees
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 96 kb/s (default)
Metadata:
handler_name : SoundHandler
Stream #0:2(und): Audio: mp3 (mp4a / 0x6134706D), 44100 Hz, stereo, s16p, 319 kb/s
Metadata:
handler_name : SoundHandler
Stream #0:3(und): Audio: mp3 (mp4a / 0x6134706D), 44100 Hz, stereo, s16p, 319 kb/s
Metadata:
handler_name : SoundHandlerONE MORE UPDATE THIS SEEMS TO WORK :
ffmpeg -i 3.mp4 -i Saison-Please_Don%27t_Go-Guesthouse_Music.mp3 -map 0:0 -map 0:1 -map 1:0 -c:v copy -c:a copy 234.mp4 && ffmpeg -i 234.mp4 -map 0:0 -map 0:2 -acodec copy -vcodec copy new_file3.mp4
-
Segments not loading in HLS Stream encoded with FFMPEG
9 novembre 2023, par myfoxitI'm currently facing a significant issue with my transcoding pipeline. Some video files produce a corrupted m3u8 playlist, wherein a few segments load but then the process halts. Even jumping to different segments in the video player doesn't resolve the issue. However, the file in question works fine when I use third-party transcoding services that utilize ffmpeg in the background, so the problem is definitely with my FFMPEG code.


To diagnose the issue, I've tried the following steps :


- 

- Simplifying the FFMPEG command.
- Testing across different browsers, but the problem persists in every browser.
- Using various video players (It works with VLC, Bitmovin, Video.js) but not with Plyr, which I usually use. This could be because they ignore the error or are less sensitive to errors.
- My files are hosted on AWS S3, but I also tried streaming them via the Next.js public folder and a custom web server, so the issue is not related to hosting.
- Ruled out CORS as the issue.
- Attempted to detect errors using ffprobe, but found no results.
- Modified the bitrate in the playlist.
- Changed the viewing device.
- Altered the segment length, but the issue persists : with 10s segments, it's segment 2 that causes the problem ; with 5s segments, then segment 4.
- No error output is visible in ffmpeg, even when using verbose mode.






















mediastreamvalidator on Apple prints out error with provided bitrate and used bitrate but changing that also did not help.


HLS Analyzer shows a buffer stalled error.


const fs = require('fs');
const path = require('path');
const { v4: uuidv4 } = require('uuid');
require('dotenv').config();
const { processVideo } = require("./ffmpegHandler");


const VIDEO_PATH = process.env.VIDEO_PATH; 
const VIDEO_STATE = JSON.parse(process.env.VIDEO_STATE);
const VIDEO_SIZE = JSON.parse(process.env.VIDEO_SIZE);
const VIDEO_DURATION = process.env.VIDEO_DURATION;

const OUTPUT_DIRECTORY = '/tmp/output';

console.log("Video Path: " + VIDEO_PATH)
console.log("Video State: " + VIDEO_STATE)
console.log("Video Size: " + VIDEO_SIZE)
console.log("Video Duration: " + VIDEO_DURATION)

async function processLocalVideo(localPath) {
 const uniqueFolderName = uuidv4(); 
 const localOutputDirectory = path.join(OUTPUT_DIRECTORY, uniqueFolderName);

 // Ensure the output directory exists
 if (!fs.existsSync(localOutputDirectory)) {
 fs.mkdirSync(localOutputDirectory, { recursive: true });
 }

 // Process the video locally
 processVideo(localPath, VIDEO_STATE, VIDEO_SIZE, VIDEO_DURATION, (err, message) => {
 if (err) {
 console.error('Error processing video:', err);
 return;
 }
 console.log('Video processing complete. HLS files are located at:', localOutputDirectory);
 });
}

// Start the processing
processLocalVideo(VIDEO_PATH).catch((error) => {
 console.error('An error occurred during video processing:', error);
});





const {exec} = require("child_process");
const ffmpegPath = require("ffmpeg-static");
const fs = require("fs");
const path = require("path");
const {spawn} = require("child_process");
const {generateArgs} = require("./generateArgs");
const {getResolutions, printDirectoryStructure, createMasterPlaylistContent} = require("./utility");


const OUTPUT_DIR = '/tmp/output';


function processVideo(filePath, imageState, size, duration, callback) {


 if (!fs.existsSync(OUTPUT_DIR)) {
 fs.mkdirSync(OUTPUT_DIR, {recursive: true});
 }

 const resolutions = getResolutions(size);
 const outputHLSPath = path.join(OUTPUT_DIR, 'dest.m3u8');
 const segmentPattern = 'segment_%03d.ts';
 const outputSegmentPath = path.join(OUTPUT_DIR, segmentPattern);

 const ffmpegPromises = resolutions.map(resolution => {
 return new Promise((resolve, reject) => {
 const scaleFilter = `scale=w=${resolution.width}:h=${resolution.height}`;
 const outputHLSPath = path.join(OUTPUT_DIR, resolution.label, 'dest.m3u8');
 const segmentPattern = `segment_%03d.ts`;
 const outputSegmentPath = path.join(OUTPUT_DIR, resolution.label, segmentPattern);

 // Ensure resolution-specific directory exists
 if (!fs.existsSync(path.join(OUTPUT_DIR, resolution.label))) {
 fs.mkdirSync(path.join(OUTPUT_DIR, resolution.label), {recursive: true});
 }

 const args = generateArgs(filePath, imageState, size, duration, resolution);


 const resolutionArgs = [
 ...args,
 '-hls_segment_filename', outputSegmentPath,
 outputHLSPath
 ];

 console.log(resolutionArgs)

 const command = `${ffmpegPath} ${resolutionArgs.join(" ")}`;


 const ffmpeg = spawn(ffmpegPath, resolutionArgs);


 ffmpeg.on('error', (error) => {
 console.error(`Error with FFmpeg process: ${error.message}`);
 reject(error);
 });

 ffmpeg.stderr.on('data', (data) => {
 console.error(`FFmpeg stderr: ${data}`);
 });

 ffmpeg.on('close', (code) => {
 if (code !== 0) {
 reject(new Error(`FFmpeg process exited with code ${code}`));
 } else {
 resolve();
 }
 });
 });
 });


 Promise.all(ffmpegPromises)
 .then(() => {
 const masterPlaylistContent = createMasterPlaylistContent(resolutions, OUTPUT_DIR);
 const masterPlaylistPath = path.join(OUTPUT_DIR, 'master.m3u8');
 fs.writeFileSync(masterPlaylistPath, masterPlaylistContent);

 printDirectoryStructure('/tmp/output', (err) => {
 if (err) {
 console.error(err);
 callback(err);
 } else {
 console.log('Directory structure printed successfully.');
 callback(null, 'All files processed successfully!');
 }
 });
 })
 .catch((error) => {
 callback(error);
 });
}


module.exports = {
 processVideo,
};








const {getColorMatrixFromColorMatrices, isNumber} = require("./utility");

function generateArgs(filePath, imageState, size, duration, resolution){
 const args = [];
 const filters = [];

 args.push("-i", filePath);


 const {
 flipX,
 flipY,
 rotation,
 crop,
 trim,
 gamma,
 colorMatrix,
 convolutionMatrix,
 } = imageState;

 console.log(crop);

 // 1. Flip
 if (flipX || flipY) {
 flipX && filters.push(`hflip`);
 flipY && filters.push(`vflip`);
 }

 // 2. Rotate
 if (rotation) {
 const width =
 Math.abs(size.width * Math.sin(rotation)) +
 Math.abs(size.height * Math.cos(rotation));

 const height =
 Math.abs(size.width * Math.cos(rotation)) +
 Math.abs(size.height * Math.sin(rotation));

 filters.push(
 `rotate='${rotation}:ow=${Math.floor(width)}:oh=${Math.floor(height)}'`
 );
 }

 // 3. Crop
 if (
 !(
 crop.x === 0 &&
 crop.y === 0 &&
 crop.width === size.width &&
 crop.height === size.height
 )
 ) {
 filters.push(`crop=${crop.width}:${crop.height}:${crop.x}:${crop.y}`);
 }


 // 5. Convolution Matrix
 if (convolutionMatrix && convolutionMatrix.clarity) {
 filters.push(`convolution='${convolutionMatrix.clarity.join(" ")}'`);
 }

 // 6. Gamma
 if (gamma > 0) {
 filters.push(`eq=gamma=${gamma}:gamma_weight=0.85`);
 }

 // 7. Color Matrix
 const colorMatrices = Object.values(colorMatrix || {}).filter(Boolean);
 if (colorMatrices.length) {
 // See helper section below for the getColorMatrixFromColorMatrices function definition
 const colorMatrix = getColorMatrixFromColorMatrices(colorMatrices);
 const skip = [4, 9, 14, 19];
 const cl = colorMatrix;
 const ccm = colorMatrix.filter((v, i) => !skip.includes(i));
 const [ro, go, bo] = [cl[4] + cl[3], cl[9] + cl[8], cl[14] + cl[13]];
 filters.push(
 `colorchannelmixer=${ccm.join(":")}`,
 `lutrgb=r=val+(${ro * 255}):g=val+(${go * 255}):b=val+(${bo * 255})`
 );
 }


 if (resolution) {
 const scaleFilter = `scale=w=${resolution.width}:h=${resolution.height}`;
 filters.push(scaleFilter);
 }


 // 8. Trim
 if (trim) {
 const inputRanges = (
 Array.isArray(trim) && isNumber(trim[0]) ? [trim] : trim
 )
 .map((range, index) => {
 const from = range[0] * duration;
 const to = range[1] * duration;
 const v = `[0:v]trim=start=${from}:end=${to},setpts=PTS-STARTPTS${filters
 .map((filter) => "," + filter)
 .join("")}[${index}v];`;
 const a = `[0:a]atrim=start=${from}:end=${to},asetpts=PTS-STARTPTS[${index}a];`;
 return v + a;
 })
 .join("");


 filters.length = 0;

 const inputRangesKeys = trim
 .map((_, index) => `[${index}v][${index}a]`)
 .join("");

 const concatOutput = `${inputRangesKeys}concat=n=${trim.length}:v=1:a=1[outv][outa]`;

 args.push("-filter_complex", `${inputRanges}${concatOutput}`);
 args.push("-map", "[outv]", "-map", "[outa]");
 } else {
 filters.length && args.push("-filter_complex", `${filters.join(",")}`);
 }


 // Add output file
 args.push(
 "-codec:v",
 "libx264",
 "-crf",
 "21",
 "-preset",
 "veryfast",
 "-g",
 "30",
 "-sc_threshold",
 "0",
 "-hls_time",
 "10",
 "-hls_list_size",
 "0",

 );

 return args
}

module.exports = {
 generateArgs,
};






const {exec} = require("child_process");


function isNumber(value) {
 return typeof value === "number" && !isNaN(value);
}

function getColorMatrixFromColorMatrices(colorMatrices) {
 return colorMatrices.length
 ? colorMatrices.reduce(
 (previous, current) => dotColorMatrix([...previous], current),
 colorMatrices.shift()
 )
 : [];
}

function dotColorMatrix(a, b) {
 const res = new Array(20);

 // R
 res[0] = a[0] * b[0] + a[1] * b[5] + a[2] * b[10] + a[3] * b[15];
 res[1] = a[0] * b[1] + a[1] * b[6] + a[2] * b[11] + a[3] * b[16];
 res[2] = a[0] * b[2] + a[1] * b[7] + a[2] * b[12] + a[3] * b[17];
 res[3] = a[0] * b[3] + a[1] * b[8] + a[2] * b[13] + a[3] * b[18];
 res[4] = a[0] * b[4] + a[1] * b[9] + a[2] * b[14] + a[3] * b[19] + a[4];

 // G
 res[5] = a[5] * b[0] + a[6] * b[5] + a[7] * b[10] + a[8] * b[15];
 res[6] = a[5] * b[1] + a[6] * b[6] + a[7] * b[11] + a[8] * b[16];
 res[7] = a[5] * b[2] + a[6] * b[7] + a[7] * b[12] + a[8] * b[17];
 res[8] = a[5] * b[3] + a[6] * b[8] + a[7] * b[13] + a[8] * b[18];
 res[9] = a[5] * b[4] + a[6] * b[9] + a[7] * b[14] + a[8] * b[19] + a[9];

 // B
 res[10] = a[10] * b[0] + a[11] * b[5] + a[12] * b[10] + a[13] * b[15];
 res[11] = a[10] * b[1] + a[11] * b[6] + a[12] * b[11] + a[13] * b[16];
 res[12] = a[10] * b[2] + a[11] * b[7] + a[12] * b[12] + a[13] * b[17];
 res[13] = a[10] * b[3] + a[11] * b[8] + a[12] * b[13] + a[13] * b[18];
 res[14] = a[10] * b[4] + a[11] * b[9] + a[12] * b[14] + a[13] * b[19] + a[14];

 // A
 res[15] = a[15] * b[0] + a[16] * b[5] + a[17] * b[10] + a[18] * b[15];
 res[16] = a[15] * b[1] + a[16] * b[6] + a[17] * b[11] + a[18] * b[16];
 res[17] = a[15] * b[2] + a[16] * b[7] + a[17] * b[12] + a[18] * b[17];
 res[18] = a[15] * b[3] + a[16] * b[8] + a[17] * b[13] + a[18] * b[18];
 res[19] = a[15] * b[4] + a[16] * b[9] + a[17] * b[14] + a[18] * b[19] + a[19];

 return res;
}

function getResolutions(videoSize) {
 // Define the resolutions
 const resolutions = [
 {width: 1280, height: 720, label: "720p", bandwidth: "1400000"},
 {width: 854, height: 480, label: "480p", bandwidth: "800000"},
 {width: 426, height: 240, label: "240p", bandwidth: "600000"}
 ];

 // Filter out resolutions that are larger than the video's original size
 return resolutions.filter(res => res.width <= videoSize.width);
}


function printDirectoryStructure(directory, callback) {
 exec(`find '${directory}' -print`, (error, stdout, stderr) => {
 if (error) {
 console.error(`exec error: ${error}`);
 return callback(error);
 }
 if (stderr) {
 console.error(`stderr: ${stderr}`);
 return callback(stderr);
 }
 console.log(`Directory structure of ${directory}:\n${stdout}`);
 callback(null);
 });
}


function createMasterPlaylistContent(resolutions, outputDir) {
 let content = '#EXTM3U\n#EXT-X-VERSION:3\n';
 resolutions.forEach((resolution) => {
 content += `#EXT-X-STREAM-INF:BANDWIDTH=${resolution.bandwidth},RESOLUTION=${resolution.width}x${resolution.height}\n`;
 content += `${resolution.label}/dest.m3u8\n`;
 });
 return content;
}


function getKeyFromUrl(url) {
 const urlParts = new URL(url);
 return urlParts.pathname.substring(1);
}


module.exports = {
 getResolutions,
 getColorMatrixFromColorMatrices,
 isNumber,
 printDirectoryStructure,
 createMasterPlaylistContent,
 getKeyFromUrl
};