
Recherche avancée
Médias (91)
-
Collections - Formulaire de création rapide
19 février 2013, par
Mis à jour : Février 2013
Langue : français
Type : Image
-
Les Miserables
4 juin 2012, par
Mis à jour : Février 2013
Langue : English
Type : Texte
-
Ne pas afficher certaines informations : page d’accueil
23 novembre 2011, par
Mis à jour : Novembre 2011
Langue : français
Type : Image
-
The Great Big Beautiful Tomorrow
28 octobre 2011, par
Mis à jour : Octobre 2011
Langue : English
Type : Texte
-
Richard Stallman et la révolution du logiciel libre - Une biographie autorisée (version epub)
28 octobre 2011, par
Mis à jour : Octobre 2011
Langue : English
Type : Texte
-
Rennes Emotion Map 2010-11
19 octobre 2011, par
Mis à jour : Juillet 2013
Langue : français
Type : Texte
Autres articles (70)
-
Mise à jour de la version 0.1 vers 0.2
24 juin 2013, parExplications des différents changements notables lors du passage de la version 0.1 de MediaSPIP à la version 0.3. Quelles sont les nouveautés
Au niveau des dépendances logicielles Utilisation des dernières versions de FFMpeg (>= v1.2.1) ; Installation des dépendances pour Smush ; Installation de MediaInfo et FFprobe pour la récupération des métadonnées ; On n’utilise plus ffmpeg2theora ; On n’installe plus flvtool2 au profit de flvtool++ ; On n’installe plus ffmpeg-php qui n’est plus maintenu au (...) -
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 ;
-
MediaSPIP v0.2
21 juin 2013, parMediaSPIP 0.2 est la première version de MediaSPIP stable.
Sa date de sortie officielle est le 21 juin 2013 et est annoncée ici.
Le fichier zip ici présent contient uniquement les sources de MediaSPIP en version standalone.
Comme pour la version précédente, il est nécessaire d’installer manuellement l’ensemble des dépendances logicielles sur le serveur.
Si vous souhaitez utiliser cette archive pour une installation en mode ferme, il vous faudra également procéder à d’autres modifications (...)
Sur d’autres sites (10529)
-
Use "JPEG 2000" as long name for j2k.
28 septembre 2011, par Carl Eugen HoyosUse "JPEG 2000" as long name for j2k.
-
hwcontext_vulkan : fix downloads ; use the common host map function to map frame data
13 mars, par Lynnehwcontext_vulkan : fix downloads ; use the common host map function to map frame data
This commit uses the recently exported code for host mapping images back
where it was exported from.The function also had broken download code for image downloading since its
recent refactor. -
Error : Cannot find ffmpeg in firebase cloud function
6 novembre 2024, par Ahmed Wagdii'm trying to compress some uploaded files to firebase storage .. using firebase cloud functions but it give me the error
Error: Cannot find ffmpeg


here is my function :


const functions = require("firebase-functions");
const admin = require("firebase-admin");
const ffmpeg = require("fluent-ffmpeg");
const ffmpegStatic = require("ffmpeg-static");
const axios = require("axios");

// const {onSchedule} = require("firebase-functions/v2/scheduler");

admin.initializeApp();

// Ensure fluent-ffmpeg uses the binary
ffmpeg.setFfmpegPath(ffmpegStatic.path);

const db = admin.firestore();
const bucket = admin.storage().bucket();
const fs = require("fs");
const downloadVideo = async (url, outputPath) => {
 const response = await axios.get(url, {responseType: "stream"});
 const writer = fs.createWriteStream(outputPath);
 response.data.pipe(writer);
 return new Promise((resolve, reject) => {
 writer.on("finish", () => resolve(outputPath));
 writer.on("error", reject);
 });
};

const compressVideo = (videoFullPath, outputFileName, targetSize) => {
 return new Promise((resolve, reject) => {
 ffmpeg.ffprobe(videoFullPath, (err, metadata) => {
 if (err) return reject(err);
 const duration = parseFloat(metadata.format.duration);
 const targetTotalBitrate =
 (targetSize * 1024 * 8) / (1.073741824 * duration);

 let audioBitrate =
 metadata.streams.find((s) => s.codec_type === "audio").bit_rate;
 if (10 * audioBitrate > targetTotalBitrate) {
 audioBitrate = targetTotalBitrate / 10;
 }

 const videoBitrate = targetTotalBitrate - audioBitrate;
 ffmpeg(videoFullPath)
 .output(outputFileName)
 .videoCodec("libx264")
 .audioCodec("aac")
 .videoBitrate(videoBitrate)
 .audioBitrate(audioBitrate)
 .on("end", resolve)
 .on("error", reject)
 .run();
 });
 });
};

const uploadVideoWithResumableUpload = (filePath, destinationBlobName) => {
 const blob = bucket.file(destinationBlobName);
 const options = {resumable: true, validation: "crc32c"};
 return blob.createWriteStream(options).end(fs.readFileSync(filePath));
};

exports.processLessonsOnDemand =
functions.https.onRequest({timeoutSeconds: 3600, memory: "2GB"}
 , async (context) => {
 console.log("Fetching lessons from Firestore...");
 const lessonsRef = db.collection("leassons");
 const lessonsSnapshot = await lessonsRef.get();

 if (lessonsSnapshot.empty) {
 console.log("No lessons found in Firestore.");
 return; // Exit if no lessons are available
 }

 const lessonDoc = lessonsSnapshot.docs[0]; // Get the first document
 const lessonData = lessonDoc.data();

 if (lessonData.shrinked) {
 console.log(
 `Skipping lesson ID ${lessonDoc.id} as it's already shrunk.`,
 );
 return; // Exit if the first lesson is already shrunk
 }

 const videoURL = lessonData.videoURL;
 if (!videoURL) {
 console.log(
 `No video URL for lesson ID: ${lessonDoc.id}. Skipping...`,
 );
 return; // Exit if no video URL is available
 }

 const tempVideoPath = "/tmp/temp_video.mp4";

 try {
 await downloadVideo(videoURL, tempVideoPath);

 const targetSize = (fs.statSync(tempVideoPath).size * 0.30) / 1024;
 const outputCompressedVideo = `/tmp/compressed_${lessonDoc.id}.mp4`;

 await compressVideo(tempVideoPath, outputCompressedVideo, targetSize);

 await uploadVideoWithResumableUpload(
 outputCompressedVideo,
 `compressed_videos/compressed_${lessonDoc.id}.mp4`,
 );

 const newVideoURL = `https://storage.googleapis.com/${bucket.name}/compressed_videos/compressed_${lessonDoc.id}.mp4`;

 const oldVideoPath = videoURL.replace(`https://storage.googleapis.com/${bucket.name}/`, "");
 const oldBlob = bucket.file(oldVideoPath);
 await oldBlob.delete();

 await lessonsRef.doc(lessonDoc.id).update({
 videoURL: newVideoURL,
 shrinked: true,
 });

 console.log(`Processed lesson ID: ${lessonDoc.id}`);
 fs.unlinkSync(tempVideoPath); // Clean up temporary files
 fs.unlinkSync(outputCompressedVideo); // Clean up compressed file
 } catch (error) {
 console.error(`Error processing lesson ID ${lessonDoc.id}:`, error);
 }
 });