
Recherche avancée
Médias (1)
-
La conservation du net art au musée. Les stratégies à l’œuvre
26 mai 2011
Mis à jour : Juillet 2013
Langue : français
Type : Texte
Autres articles (109)
-
Le profil des utilisateurs
12 avril 2011, parChaque utilisateur dispose d’une page de profil lui permettant de modifier ses informations personnelle. Dans le menu de haut de page par défaut, un élément de menu est automatiquement créé à l’initialisation de MediaSPIP, visible uniquement si le visiteur est identifié sur le site.
L’utilisateur a accès à la modification de profil depuis sa page auteur, un lien dans la navigation "Modifier votre profil" est (...) -
MediaSPIP Core : La Configuration
9 novembre 2010, parMediaSPIP Core fournit par défaut trois pages différentes de configuration (ces pages utilisent le plugin de configuration CFG pour fonctionner) : une page spécifique à la configuration générale du squelettes ; une page spécifique à la configuration de la page d’accueil du site ; une page spécifique à la configuration des secteurs ;
Il fournit également une page supplémentaire qui n’apparait que lorsque certains plugins sont activés permettant de contrôler l’affichage et les fonctionnalités spécifiques (...) -
ANNEXE : Les plugins utilisés spécifiquement pour la ferme
5 mars 2010, parLe site central/maître de la ferme a besoin d’utiliser plusieurs plugins supplémentaires vis à vis des canaux pour son bon fonctionnement. le plugin Gestion de la mutualisation ; le plugin inscription3 pour gérer les inscriptions et les demandes de création d’instance de mutualisation dès l’inscription des utilisateurs ; le plugin verifier qui fournit une API de vérification des champs (utilisé par inscription3) ; le plugin champs extras v2 nécessité par inscription3 (...)
Sur d’autres sites (10362)
-
Video streamign with FFMpeg and Nest.js+Next.js
17 septembre 2024, par AizenHere is my problem : I have one video src 1080p (on the frontend). On the frontend, I send this video-route to the backend :


const req = async()=>{try{const res = await axios.get('/catalog/item',{params:{SeriesName:seriesName}});return {data:res.data};}catch(err){console.log(err);return false;}}const fetchedData = await req();-On the backend i return seriesName.Now i can make a full path,what the video is,and where it is,code:



const videoUrl = 'C:/Users/arMori/Desktop/RedditClone/reddit/public/videos';console.log('IT VideoURL',videoUrl);



const selectedFile = `${videoUrl}/${fetchedData.data.VideoSource}/${seriesName}-1080p.mp4`
console.log(`ITS'S SELECTED FILE: ${selectedFile}`);



Ok, I have my src 1080p, now is the time to send it to the backend :


const response = await axios.post('/videoFormat', {videoUrl:selectedFile})console.log('Это консоль лог путей: ',response.data);const videoPaths = response.data;



Backend takes it and FFMpqg makes two types of resolution,720p and 480p,save it to the temp storage on backend, and then returns two routes where these videos stores


async videoUpload(videoUrl:string){try{const tempDir = C:/Users/arMori/Desktop/RedditClone/reddit_back/src/video/temp;const inputFile = videoUrl;console.log('VIDEOURL: ',videoUrl);



const outputFiles = [];
 
 await this.createDirectories(tempDir); 
 outputFiles.push(await this.convertVideo(inputFile, '1280x720', '720p.mp4'));
 outputFiles.push(await this.convertVideo(inputFile, '854x480', '480p.mp4'));
 console.log('OUTUPT FILES SERVICE: ',outputFiles);
 
 return outputFiles;

 }catch(err){
 console.error('VideoFormatterService Error: ',err);
 
 }
}

private convertVideo(inputPath:string,resolution:string,outputFileName:string):Promise<string>{
 const temp = `C:/Users/arMori/Desktop/RedditClone/reddit_back/src/video/temp`;
 return new Promise(async(resolve,reject)=>{
 const height = resolution.split('x')[1];
 console.log('HIEGHT: ',height);
 
 const outputDir = `C:/Users/arMori/Desktop/RedditClone/reddit_back/src/video/temp/${height}p`;
 const outputPath = join(outputDir, outputFileName);
 const isExists = await fs.access(outputPath).then(() => true).catch(() => false);
 if(isExists){ 
 console.log(`File already exists: ${outputPath}`);
 return resolve(outputPath)
 };
 ffmpeg(inputPath)
 .size(`${resolution}`)
 .videoCodec('libx264') // Кодек H.264
 .audioCodec('aac') 
 .output(outputPath)
 .on('end',()=>resolve(outputPath))
 .on('error',(err)=>reject(err))
 .run()
 
 })
}

private async createDirectories(temp:string){
 try{
 const dir720p = `${temp}/720p`;
 const dir480p = `${temp}/480p`;
 const dir720pExists = await fs.access(dir720p).then(() => true).catch(() => false);
 const dir480pExists = await fs.access(dir480p).then(() => true).catch(() => false);
 if(dir720pExists && dir480pExists){
 console.log('FILES ALIVE');
 return;
 }
 if (!dir720pExists) {
 await fs.mkdir(dir720p, { recursive: true });
 console.log('Папка 720p создана');
 }
 
 if (!dir480pExists) {
 await fs.mkdir(dir480p, { recursive: true });
 console.log('Папка 480p создана');
 }
 } catch (err) {
 console.error('Ошибка при создании директорий:', err);
 }
}
</string>


Continue frontentd code :


let videoPath;

if (quality === '720p') {
 videoPath = videoPaths[0];
} else if (quality === '480p') {
 videoPath = videoPaths[1];
}

if (!videoPath) {
 console.error('Video path not found!');
 return;
}

// Получаем видео по его пути
console.log('VIDEOPATH LOG: ',videoPath);
 
const videoRes = await axios.get('/videoFormat/getVideo', { 
 params: { path: videoPath } ,
 headers: { Range: 'bytes=0-' },
 responseType: 'blob'
 });
 console.log('Video fetched: ', videoRes);
 const videoBlob = new Blob([videoRes.data], { type: 'video/mp4' });
 const videoURL = URL.createObjectURL(videoBlob);
 return videoURL;
 /* console.log('Видео успешно загружено:', response.data); */
 } catch (error) {
 console.error('Ошибка при загрузке видео:', error);
 }
}



Here I just choose one of the route and make a new GET request (VideoRes), now in the controller in the backend, I'm trying to do a video streaming :


@Public()
 @Get('/getVideo')
 async getVideo(@Query('path') videoPath:string,@Req() req:Request,@Res() res:Response){
 try {
 console.log('PATH ARGUMENT: ',videoPath);
 console.log('VIDEOPATH IN SERVICE: ',videoPath);
 const videoSize = (await fs.stat(videoPath)).size;
 const CHUNK_SIZE = 10 ** 6;
 const range = req.headers['range'] as string | undefined;
 if (!range) {
 return new ForbiddenException('Range не найденно');
 }
 const start = Number(range.replace(/\D/g,""));
 const end = Math.min(start + CHUNK_SIZE,videoSize - 1);

 const contentLength = end - start + 1;
 const videoStream = fsSync.createReadStream(videoPath, { start, end });
 const headers = {
 'Content-Range':`bytes ${start}-${end}/${videoSize}`,
 'Accept-Ranges':'bytes',
 'Content-Length':contentLength,
 'Content-Type':'video/mp4'
 }
 
 res.writeHead(206,headers);

 // Передаем поток в ответ
 videoStream.pipe(res);
 

 // Если возникнет ошибка при стриминге, логируем ошибку
 videoStream.on('error', (error) => {
 console.error('Ошибка при чтении видео:', error);
 res.status(500).send('Ошибка при чтении видео');
 });
 } catch (error) {
 console.error('Ошибка при обработке запросов:', error);
 return res.status(400).json({ message: 'Ошибка при обработке getVideo запросов' });
 }
 }



Send to the frontend


res.writeHead(206,headers);



In the frontend, I make blob url for video src and return it


const videoBlob = new Blob([videoRes.data], { type: 'video/mp4' });const videoURL = URL.createObjectURL(videoBlob);return videoURL;



And assign src to the video :


useVideo(seriesName,quality).then(src => {
 if (src) {
 console.log('ITS VIDEOLOGISC GOIDA!');
 if(!playRef.current) return;
 
 const oldURL = playRef.current.src;
 if (oldURL && oldURL.startsWith('blob:')) {
 URL.revokeObjectURL(oldURL);
 }
 playRef.current.pause();
 playRef.current.src = '';
 setQuality(quality);
 console.log('SRC: ',src);
 
 playRef.current.src = src;
 playRef.current.load();
 console.log('ITS VIDEOURL GOIDA!');
 togglePlayPause();
 }
 })
 .catch(err => console.error('Failed to fetch video', err));



But the problem is :




Vinland-Saga:1 Uncaught (in promise) NotSupportedError : Failed to load because no supported source was found




And I don't know why...


I tried everything, but I don't understand why src is incorrect..


-
Revision 56d048c412 : Moving mv entropy encodings calculation to the encoder side. Moved arrays : vp
26 novembre 2013, par Dmitry KovalevChanged Paths :
Modify /vp9/common/vp9_alloccommon.c
Modify /vp9/common/vp9_entropymv.c
Modify /vp9/common/vp9_entropymv.h
Modify /vp9/encoder/vp9_encodemv.c
Modify /vp9/encoder/vp9_encodemv.h
Modify /vp9/encoder/vp9_onyx_if.c
Moving mv entropy encodings calculation to the encoder side.Moved arrays :
vp9_mv_joint_encodings
vp9_mv_class_encodings
vp9_mv_class0_encodings
vp9_mv_fp_encodingsChange-Id : Iaf5008c579fcbd6d77fdd81d1aef8c71b5f308b7
-
Revision 7ab9a9587b : Remove Wextra warnings from vp9_sad.c As a side-effect, the max_sad check is re
13 mai 2014, par Deb MukherjeeChanged Paths :
Modify /test/sad_test.cc
Modify /vp8/common/rtcd_defs.pl
Modify /vp8/common/sad_c.c
Modify /vp8/common/variance.h
Modify /vp8/encoder/mcomp.c
Modify /vp8/encoder/rdopt.c
Modify /vp9/common/vp9_rtcd_defs.pl
Modify /vp9/encoder/vp9_encodeframe.c
Modify /vp9/encoder/vp9_mbgraph.c
Modify /vp9/encoder/vp9_mcomp.c
Modify /vp9/encoder/vp9_rdopt.c
Modify /vp9/encoder/vp9_sad.c
Modify /vp9/encoder/vp9_variance.h
Remove Wextra warnings from vp9_sad.cAs a side-effect, the max_sad check is removed from the
C-implementation of VP8, for consistency with VP9, and to
ensure that the SAD tests common to VP8/VP9 pass.
That will make the VP8 C implementation of sad a little slower
but given that is rarely used in practice, the impact will be
minimal.Change-Id : I7f43089fdea047fbf1862e40c21e4715c30f07ca