
Recherche avancée
Autres articles (44)
-
Les formats acceptés
28 janvier 2010, parLes commandes suivantes permettent d’avoir des informations sur les formats et codecs gérés par l’installation local de ffmpeg :
ffmpeg -codecs ffmpeg -formats
Les format videos acceptés en entrée
Cette liste est non exhaustive, elle met en exergue les principaux formats utilisés : h264 : H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 m4v : raw MPEG-4 video format flv : Flash Video (FLV) / Sorenson Spark / Sorenson H.263 Theora wmv :
Les formats vidéos de sortie possibles
Dans un premier temps on (...) -
Submit bugs and patches
13 avril 2011Unfortunately a software is never perfect.
If you think you have found a bug, report it using our ticket system. Please to help us to fix it by providing the following information : the browser you are using, including the exact version as precise an explanation as possible of the problem if possible, the steps taken resulting in the problem a link to the site / page in question
If you think you have solved the bug, fill in a ticket and attach to it a corrective patch.
You may also (...) -
Publier sur MédiaSpip
13 juin 2013Puis-je poster des contenus à partir d’une tablette Ipad ?
Oui, si votre Médiaspip installé est à la version 0.2 ou supérieure. Contacter au besoin l’administrateur de votre MédiaSpip pour le savoir
Sur d’autres sites (6567)
-
Merge file without data loss using FFmpeg inside of WASM
9 septembre 2023, par DejiEdit : I'm rewriting this entire question


Goal : To reconstruct a video from its pieces/chunks from a network stream inside of an
@ffmpeg/ffmpeg
worker

Problems :


- 

- Video chunks/pieces which come after the first piece/chunk are reported by
@ffmpeg/ffmpeg
to have invalid data, as seen in the log below :




{
 "type": "stderr",
 "message": "video-0_chunk-1.part: Invalid data found when processing input"
}



- 

- How would I merge these chunks/pieces to reconstruct the full video using
@ffmpeg/ffmpeg
(after solving the first issue above)




My current code situation :


- 

- For merging the video pieces




const constructFile = async (chunks: Uint8Array[], queueId: number) => {
 await Promise.all(
 chunks.map(async (chunk, index) => {
 const chunkFile = `video-${queueId}_chunk-${index}`;
 await ffmpeg.writeFile(chunkFile, chunk);

 // Return information about newly created file
 ffmpeg.exec(["-i", chunkFile]);
 })
 );
};



I'm reading the logs/output for


ffmpeg.exec(['-i', chunkFile])



using


ffmpeg.on('log', (log) => console.log(log))



- 

- For fetching the videos using streams




await useFetch(Capacitor.convertFileSrc(file.path), {
 responseType: "stream",

 onResponse: async ({ response }) => {
 if (response.body) {
 const reader = response.body.getReader();

 while (true) {
 const { done, value } = await reader.read();

 if (done) break;
 file.chunks.push(value);
 }
 reader.releaseLock();
 }
 },
});



Note : file.chunks is linked to a reactive value which is passed to
constructFile()
when initialized

These are the logs I get from the code currently above :


chunk-4OF65L5M.js:2710 <suspense> is an experimental feature and its API will likely change.
(index):298 native App.addListener (#25407936)
(index):298 native FilePicker.pickVideos (#25407937)
(index):272 result FilePicker.pickVideos (#25407937)
(index):298 native VideoEditor.thumbnail (#25407938)
(index):272 result VideoEditor.thumbnail (#25407938)
Processing.vue:135 {type: 'stderr', message: 'ffmpeg version 5.1.3 Copyright (c) 2000-2022 the FFmpeg developers'}
Processing.vue:135 {type: 'stderr', message: ' built with emcc (Emscripten gcc/clang-like repla…3.1.40 (5c27e79dd0a9c4e27ef2326841698cdd4f6b5784)'}
Processing.vue:135 {type: 'stderr', message: ' configuration: --target-os=none --arch=x86_32 --…e-libfreetype --enable-libfribidi --enable-libass'}
Processing.vue:135 {type: 'stderr', message: ' libavutil 57. 28.100 / 57. 28.100'}
Processing.vue:135 {type: 'stderr', message: ' libavcodec 59. 37.100 / 59. 37.100'}
Processing.vue:135 {type: 'stderr', message: ' libavformat 59. 27.100 / 59. 27.100'}
Processing.vue:135 {type: 'stderr', message: ' libavdevice 59. 7.100 / 59. 7.100'}
Processing.vue:135 {type: 'stderr', message: ' libavfilter 8. 44.100 / 8. 44.100'}
Processing.vue:135 {type: 'stderr', message: ' libswscale 6. 7.100 / 6. 7.100'}
Processing.vue:135 {type: 'stderr', message: ' libswresample 4. 7.100 / 4. 7.100'}
Processing.vue:135 {type: 'stderr', message: ' libpostproc 56. 6.100 / 56. 6.100'}
Processing.vue:135 {type: 'stderr', message: "Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'video-0_chunk-0':"}
Processing.vue:135 {type: 'stderr', message: ' Metadata:'}
Processing.vue:135 {type: 'stderr', message: ' major_brand : mp42'}
Processing.vue:135 {type: 'stderr', message: ' minor_version : 0'}
Processing.vue:135 {type: 'stderr', message: ' compatible_brands: isommp42'}
Processing.vue:135 {type: 'stderr', message: ' creation_time : 2022-11-29T14:46:32.000000Z'}
Processing.vue:135 {type: 'stderr', message: ' Duration: 00:00:51.50, start: 0.000000, bitrate: 81 kb/s'}
Processing.vue:135 {type: 'stderr', message: ' Stream #0:0[0x1](und): Video: h264 (High) (avc1 …6], 259 kb/s, 30 fps, 30 tbr, 15360 tbn (default)'}
Processing.vue:135 {type: 'stderr', message: ' Metadata:'}
Processing.vue:135 {type: 'stderr', message: ' creation_time : 2022-11-29T14:46:32.000000Z'}
Processing.vue:135 {type: 'stderr', message: ' handler_name : ISO Media file produced by Google Inc. Created on: 11/29/2022.'}
Processing.vue:135 {type: 'stderr', message: ' vendor_id : [0][0][0][0]'}
Processing.vue:135 {type: 'stderr', message: ' Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0…706D), 44100 Hz, stereo, fltp, 127 kb/s (default)'}
Processing.vue:135 {type: 'stderr', message: ' Metadata:'}
Processing.vue:135 {type: 'stderr', message: ' creation_time : 2022-11-29T14:46:32.000000Z'}
Processing.vue:135 {type: 'stderr', message: ' handler_name : ISO Media file produced by Google Inc. Created on: 11/29/2022.'}
Processing.vue:135 {type: 'stderr', message: ' vendor_id : [0][0][0][0]'}
Processing.vue:135 {type: 'stderr', message: 'At least one output file must be specified'}
Processing.vue:135 {type: 'stderr', message: 'Aborted()'}
Processing.vue:135 {type: 'stderr', message: 'ffmpeg version 5.1.3 Copyright (c) 2000-2022 the FFmpeg developers'}
Processing.vue:135 {type: 'stderr', message: ' built with emcc (Emscripten gcc/clang-like repla…3.1.40 (5c27e79dd0a9c4e27ef2326841698cdd4f6b5784)'}
Processing.vue:135 {type: 'stderr', message: ' configuration: --target-os=none --arch=x86_32 --…e-libfreetype --enable-libfribidi --enable-libass'}
Processing.vue:135 {type: 'stderr', message: ' libavutil 57. 28.100 / 57. 28.100'}
Processing.vue:135 {type: 'stderr', message: ' libavcodec 59. 37.100 / 59. 37.100'}
Processing.vue:135 {type: 'stderr', message: ' libavformat 59. 27.100 / 59. 27.100'}
Processing.vue:135 {type: 'stderr', message: ' libavdevice 59. 7.100 / 59. 7.100'}
Processing.vue:135 {type: 'stderr', message: ' libavfilter 8. 44.100 / 8. 44.100'}
Processing.vue:135 {type: 'stderr', message: ' libswscale 6. 7.100 / 6. 7.100'}
Processing.vue:135 {type: 'stderr', message: ' libswresample 4. 7.100 / 4. 7.100'}
Processing.vue:135 {type: 'stderr', message: ' libpostproc 56. 6.100 / 56. 6.100'}
Processing.vue:135 {type: 'stderr', message: 'video-0_chunk-1: Invalid data found when processing input'}
Processing.vue:135 {type: 'stderr', message: 'Aborted()'}
Processing.vue:135 {type: 'stderr', message: 'ffmpeg version 5.1.3 Copyright (c) 2000-2022 the FFmpeg developers'}
Processing.vue:135 {type: 'stderr', message: ' built with emcc (Emscripten gcc/clang-like repla…3.1.40 (5c27e79dd0a9c4e27ef2326841698cdd4f6b5784)'}
Processing.vue:135 {type: 'stderr', message: ' configuration: --target-os=none --arch=x86_32 --…e-libfreetype --enable-libfribidi --enable-libass'}
Processing.vue:135 {type: 'stderr', message: ' libavutil 57. 28.100 / 57. 28.100'}
Processing.vue:135 {type: 'stderr', message: ' libavcodec 59. 37.100 / 59. 37.100'}
Processing.vue:135 {type: 'stderr', message: ' libavformat 59. 27.100 / 59. 27.100'}
Processing.vue:135 {type: 'stderr', message: ' libavdevice 59. 7.100 / 59. 7.100'}
Processing.vue:135 {type: 'stderr', message: ' libavfilter 8. 44.100 / 8. 44.100'}
Processing.vue:135 {type: 'stderr', message: ' libswscale 6. 7.100 / 6. 7.100'}
Processing.vue:135 {type: 'stderr', message: ' libswresample 4. 7.100 / 4. 7.100'}
Processing.vue:135 {type: 'stderr', message: ' libpostproc 56. 6.100 / 56. 6.100'}
Processing.vue:135 {type: 'stderr', message: 'video-0_chunk-2: Invalid data found when processing input'}
Processing.vue:135 {type: 'stderr', message: 'Aborted()'}
Processing.vue:135 {type: 'stderr', message: 'ffmpeg version 5.1.3 Copyright (c) 2000-2022 the FFmpeg developers'}
Processing.vue:135 {type: 'stderr', message: ' built with emcc (Emscripten gcc/clang-like repla…3.1.40 (5c27e79dd0a9c4e27ef2326841698cdd4f6b5784)'}
Processing.vue:135 {type: 'stderr', message: ' configuration: --target-os=none --arch=x86_32 --…e-libfreetype --enable-libfribidi --enable-libass'}
Processing.vue:135 {type: 'stderr', message: ' libavutil 57. 28.100 / 57. 28.100'}
Processing.vue:135 {type: 'stderr', message: ' libavcodec 59. 37.100 / 59. 37.100'}
Processing.vue:135 {type: 'stderr', message: ' libavformat 59. 27.100 / 59. 27.100'}
Processing.vue:135 {type: 'stderr', message: ' libavdevice 59. 7.100 / 59. 7.100'}
Processing.vue:135 {type: 'stderr', message: ' libavfilter 8. 44.100 / 8. 44.100'}
Processing.vue:135 {type: 'stderr', message: ' libswscale 6. 7.100 / 6. 7.100'}
Processing.vue:135 {type: 'stderr', message: ' libswresample 4. 7.100 / 4. 7.100'}
Processing.vue:135 {type: 'stderr', message: ' libpostproc 56. 6.100 / 56. 6.100'}
Processing.vue:135 {type: 'stderr', message: 'video-0_chunk-3: Invalid data found when processing input'}
Processing.vue:135 {type: 'stderr', message: 'Aborted()'}
Processing.vue:135 {type: 'stderr', message: 'ffmpeg version 5.1.3 Copyright (c) 2000-2022 the FFmpeg developers'}
Processing.vue:135 {type: 'stderr', message: ' built with emcc (Emscripten gcc/clang-like repla…3.1.40 (5c27e79dd0a9c4e27ef2326841698cdd4f6b5784)'}
Processing.vue:135 {type: 'stderr', message: ' configuration: --target-os=none --arch=x86_32 --…e-libfreetype --enable-libfribidi --enable-libass'}
Processing.vue:135 {type: 'stderr', message: ' libavutil 57. 28.100 / 57. 28.100'}
Processing.vue:135 {type: 'stderr', message: ' libavcodec 59. 37.100 / 59. 37.100'}
Processing.vue:135 {type: 'stderr', message: ' libavformat 59. 27.100 / 59. 27.100'}
Processing.vue:135 {type: 'stderr', message: ' libavdevice 59. 7.100 / 59. 7.100'}
Processing.vue:135 {type: 'stderr', message: ' libavfilter 8. 44.100 / 8. 44.100'}
Processing.vue:135 {type: 'stderr', message: ' libswscale 6. 7.100 / 6. 7.100'}
Processing.vue:135 {type: 'stderr', message: ' libswresample 4. 7.100 / 4. 7.100'}
Processing.vue:135 {type: 'stderr', message: ' libpostproc 56. 6.100 / 56. 6.100'}
Processing.vue:135 {type: 'stderr', message: 'video-0_chunk-4: Invalid data found when processing input'}
Processing.vue:135 {type: 'stderr', message: 'Aborted()'}
</suspense>


Notes :


- 

- The sections which start with
Processing.vue
come from the logging system I've setup. - The pieces/chunks gotten from the network where stored in exactly the same order in which they came
- If you've seen the old question, the
ReferenceError
happens as a result of HMR by Vite
- 

- Similar to this, some logs were repeated twice because I was actively changing some things and the component had to rerun from the start












Summary : If my problem is still not clear, you could provide another way of fetching a large file (video) from a network, loading the file into memory and passing the file data to
@ffmpeg/ffmpeg
for further processing

- Video chunks/pieces which come after the first piece/chunk are reported by
-
ffmpeg - allow to create empty aac file
27 juillet 2023, par user11149927I have two commands :


ffmpeg -y -i file.mp4 -vn -acodec copy file.aac



and then :


ffmpeg -y -i file.mp4 -i file.aac -c:v copy -c:a aac new-file.mp4



The first command throw error when the video has no audio :


Output file does not contain any stream



I would like to change first command to allow create empty aac file (maybe silent audio) when video has no audio. Or maybe exists better solution ?


-
Are there any alternatives to SharedArrayBuffer, or methods for video editing in a web browser ?
26 juillet 2023, par Govinda RegmiI'm working on a web-based video editing application using ffmeg that heavily relies on SharedArrayBuffer. Unfortunately, I've encountered a roadblock with the "Cross-Origin-Embedder-Policy : require-corp | credentialless" and "Cross-Origin-Opener-Policy : same-origin" headers. While these headers allow the usage of SharedArrayBuffer, they restrict other essential features, such as rendering images from an s3 bucket and script of TinyMce text editor.


I am trying to achieve
video editor like this


I am using "next" : "12.1.6" and
I tried to implement ffmeg like this :


import { useEffect, useState } from "react";

import { useDebounce } from "use-debounce";
import { createFFmpeg, fetchFile } from "@ffmpeg/ffmpeg";

import styles from "../videoEditor.module.scss";
import RangeInput from "../range-input/RangeInput";
import * as helpers from "../../../../utils/videoHelpers";

const FF = createFFmpeg({
 log: true,
 corePath: "https://unpkg.com/@ffmpeg/core@0.10.0/dist/ffmpeg-core.js",
});

(async function () {
 await FF.load();
})();

export const VideoTrimmer = ({
 videoFile,
 trimmedVideoFile,
 isConfirmClicked,
 setTrimmedVideoFile,
 onConfirmClickHandler,
}) => {
 const [URL, setURL] = useState([]);
 const [thumbNails, setThumbNails] = useState([]);
 const [videoMeta, setVideoMeta] = useState(null);
 const [inputVideoFile, setInputVideoFile] = useState(null);
 const [thumbnailIsProcessing, setThumbnailIsProcessing] = useState(false);

 const [rStart, setRstart] = useState(0);
 const [debouncedRstart] = useDebounce(rStart, 500);

 const [rEnd, setRend] = useState(10);
 const [debouncedRend] = useDebounce(rEnd, 500);

 const handleLoadedData = async (e) => {
 const el = e.target;
 const meta = {
 name: inputVideoFile.name,
 duration: el.duration,
 videoWidth: 50,
 videoHeight: 50,
 };
 setVideoMeta(meta);
 const thumbNails = await getThumbnails(meta);
 setThumbNails(thumbNails);
 };

 const getThumbnails = async ({ duration }) => {
 if (!FF.isLoaded()) await FF.load();
 setThumbnailIsProcessing(true);
 let MAX_NUMBER_OF_IMAGES = 15;
 let NUMBER_OF_IMAGES = duration < MAX_NUMBER_OF_IMAGES ? duration : 15;
 let offset =
 duration === MAX_NUMBER_OF_IMAGES ? 1 : duration / NUMBER_OF_IMAGES;

 const arrayOfImageURIs = [];
 FF.FS("writeFile", inputVideoFile.name, await fetchFile(inputVideoFile));

 for (let i = 0; i < NUMBER_OF_IMAGES; i++) {
 let startTimeInSecs = helpers.toTimeString(Math.round(i * offset));

 try {
 await FF.run(
 "-ss",
 startTimeInSecs,
 "-i",
 inputVideoFile.name,
 "-t",
 "00:00:1.000",
 "-vf",
 `scale=150:-1`,
 `img${i}.png`,
 );
 const data = FF.FS("readFile", `img${i}.png`);

 let blob = new Blob([data.buffer], { type: "image/png" });
 let dataURI = await helpers.readFileAsBase64(blob);
 FF.FS("unlink", `img${i}.png`);
 arrayOfImageURIs.push(dataURI);
 } catch (error) {
 // console.log({ message: error });
 }
 }
 setThumbnailIsProcessing(false);

 return arrayOfImageURIs;
 };
 const handleTrim = async () => {
 // setTrimIsProcessing(true);
 let startTime = ((rStart / 100) * videoMeta.duration).toFixed(2);
 let offset = ((rEnd / 100) * videoMeta.duration - startTime).toFixed(2);
 try {
 FF.FS("writeFile", inputVideoFile.name, await fetchFile(inputVideoFile));
 await FF.run(
 "-ss",
 helpers.toTimeString(startTime),
 "-i",
 inputVideoFile.name,
 "-t",
 helpers.toTimeString(offset),
 "-c",
 "copy",
 "ping.mp4",
 );
 const data = FF.FS("readFile", "ping.mp4");
 const dataURL = await helpers.readFileAsBase64(
 new Blob([data.buffer], { type: "video/mp4" }),
 );

 setTrimmedVideoFile(dataURL);
 } catch (error) {
 // console.log(error);
 } finally {
 // setTrimIsProcessing(false);
 }
 };

 const handleRangeChange = (type, event) => {
 const limit = parseInt((120 / videoMeta.duration) * 100);
 if (type === "start") {
 if (rEnd - rStart > limit) {
 setRend(parseInt(event.target.value) + limit);
 setRstart(parseInt(event.target.value));
 } else {
 setRstart(parseInt(event.target.value));
 }
 } else if (type === "end") {
 if (rEnd - rStart > limit) {
 setRstart(parseInt(event.target.value) - limit);
 setRend(parseInt(event.target.value));
 } else {
 setRend(parseInt(event.target.value));
 }
 }
 };

 useEffect(() => {
 if (videoMeta?.duration > 120) {
 const limit = parseInt((120 / videoMeta.duration) * 100);
 setRend(limit);
 }
 }, [videoMeta?.duration]);

 useEffect(() => {
 const videoFormData = new FormData();
 if (videoFile) {
 videoFormData.append("file", videoFile);
 const handleChange = async () => {
 setInputVideoFile(videoFile);
 setURL(await helpers.readFileAsBase64(videoFile));
 };
 handleChange();
 }
 }, []);

 useEffect(() => {
 if (videoMeta) {
 onConfirmClickHandler(handleTrim);
 }
 }, [isConfirmClicked]);

 useEffect(() => {
 if (debouncedRend == rEnd && debouncedRstart == rStart && videoMeta) {
 handleTrim();
 }
 }, [debouncedRend, debouncedRstart, videoMeta]);

 return (
 <>
 <article classname="grid_txt_2">
 
 {trimmedVideoFile ? (
 
 ) : (
 
 )}
 
 </article>
 
 >
 );
};



next.config.js


const nextConfig = {
 async headers() {
 return [
 {
 source: "/(.*)",
 headers: [
 { key: "Cross-Origin-Opener-Policy", value: "same-origin" },
 { key: "Cross-Origin-Embedder-Policy", value: "credentialless" },
 ],
 },
 ];
 },
 
};



This works seamlessly in Chrome and Edge, but it encounter issues (SharedArrayBuffer is not defined) in Firefox and Safari. How can we ensure it functions impeccably across all major browsers ?


When utilizing key : "Cross-Origin-Embedder-Policy", value : "require-corp" , I encounter an error while fetching images/scripts from cross-origin sources, resulting in "net::ERR_BLOCKED_BY_RESPONSE.NotSameOriginAfterDefaultedToSameOriginByCoep 200 (OK)". Cany you suggest me how can I resolve this issue ?