
Recherche avancée
Médias (1)
-
Rennes Emotion Map 2010-11
19 octobre 2011, par
Mis à jour : Juillet 2013
Langue : français
Type : Texte
Autres articles (80)
-
Amélioration de la version de base
13 septembre 2013Jolie sélection multiple
Le plugin Chosen permet d’améliorer l’ergonomie des champs de sélection multiple. Voir les deux images suivantes pour comparer.
Il suffit pour cela d’activer le plugin Chosen (Configuration générale du site > Gestion des plugins), puis de configurer le plugin (Les squelettes > Chosen) en activant l’utilisation de Chosen dans le site public et en spécifiant les éléments de formulaires à améliorer, par exemple select[multiple] pour les listes à sélection multiple (...) -
Emballe médias : à quoi cela sert ?
4 février 2011, parCe plugin vise à gérer des sites de mise en ligne de documents de tous types.
Il crée des "médias", à savoir : un "média" est un article au sens SPIP créé automatiquement lors du téléversement d’un document qu’il soit audio, vidéo, image ou textuel ; un seul document ne peut être lié à un article dit "média" ; -
Le plugin : Gestion de la mutualisation
2 mars 2010, parLe plugin de Gestion de mutualisation permet de gérer les différents canaux de mediaspip depuis un site maître. Il a pour but de fournir une solution pure SPIP afin de remplacer cette ancienne solution.
Installation basique
On installe les fichiers de SPIP sur le serveur.
On ajoute ensuite le plugin "mutualisation" à la racine du site comme décrit ici.
On customise le fichier mes_options.php central comme on le souhaite. Voilà pour l’exemple celui de la plateforme mediaspip.net :
< ?php (...)
Sur d’autres sites (4273)
-
Uploading video to Twitter sometimes doesn't work
22 juillet 2021, par K-s S-kI have a very difficult situation. I've already spent 2 days and couldn't find a solution. Project on Laravel. I want to upload videos to Twitter using the Twitter API endpoints. But sometimes I am getting this error :




file is currently unsupported




I did everything as recommended in the official documentation Video specifications and recommendations. I get an error when I set an audio codec is aac in my video file, despite the fact that it is recommended in the official documentation, but when I set the audio codec to mp3, the video is uploaded, but the sound quality is very poor, and sometimes there is no sound at all. Please forgive me if this is awkward to read, but I want to provide all of my code. Because I don't know how to solve this anymore and I think it might help.


<?php

namespace App\Jobs;

use App\Models\PublishedContent;
use Atymic\Twitter\Facades\Twitter;
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Bus\Queueable;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\File;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Str;


class PublishToTwitter implements ShouldQueue
{
 use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

 /**
 * @var
 */
 protected $publishingData;

 /**
 * Create a new job instance.
 *
 * @param $publishingData
 */
 public function __construct($publishingData)
 {
 $this->publishingData = $publishingData;
 }

 /**
 * Execute the job.
 *
 * @return void
 */
 public function handle()
 {
 $publishingData = $this->publishingData;

 if (is_array($publishingData)) {
 $publishingResult = $this->publishing(...array_values($publishingData));
 sendNotification($publishingResult['message'], $publishingResult['status'], 'Twitter', $publishingResult['link'], $publishingData['post_name'], $publishingData['user']);
 } else {
 $scheduledData = processingScheduledPost($publishingData);
 $postName = $scheduledData['scheduleData']['post_name'];
 $postContent = $scheduledData['scheduleData']['post_content'];
 $userToken = json_decode($publishingData->user_token,true);
 $requestToken = [
 'token' => $userToken['oauth_token'],
 'secret' => $userToken['oauth_token_secret'],
 ];
 $publishingResult = $this->publishing($scheduledData['file'], $postName, $postContent, $requestToken);
 $publishingResult['status'] && PublishedContent::add($scheduledData['craft'], $scheduledData['file'], "twitter_share");
 sendResultToUser($publishingData, $scheduledData['user'], $publishingResult['message'], $postName, $publishingResult['link'], $publishingResult['publishing_status'], $scheduledData['social_media']);
 sendNotification($publishingResult['message'], $publishingResult['status'], 'Twitter', $publishingResult['link'], $postName, $scheduledData['user']);
 }
 }

 /**
 * @param $file
 * @param $postName
 * @param $postContent
 * @param $requestToken
 * @return array
 */
 private function publishing($file, $postName, $postContent, $requestToken): array
 {
 $result = [
 'status' => false,
 'link' => null,
 'message' => 'Your content can\'t successfully published on Twitter. This file is not supported for publishing.',
 'publishing_status' => 'error'
 ];

 if ((($file->refe_type !== 'text') || $file->refe_file_path) && !checkIfFileExist($file->refe_file_path)) {
 $result['message'] = 'Missing or invalid file.';
 return $result;
 }

 $filePath = $file->refe_file_path;
 $fileSize = $file->content_length;
 $tempFileName = 'temp-' . $file->refe_file_name;
 $ext = $file->file_type;
 $mediaCategory = 'tweet_' . $file->refe_type;
 $mediaType = $file->refe_type . '/' . $ext;
 $remoteFile = file_get_contents($filePath);
 $tempFolder = public_path('/storage/uploads/temp');

 if (!file_exists($tempFolder)) {
 mkdir($tempFolder, 0777, true);
 }

 $tempFile = public_path('/storage/uploads/temp/' . $tempFileName);
 File::put($tempFile, $remoteFile);
 $convertedFileName = 'converted-' . $file->refe_file_name;
 $convertedFile = public_path('/storage/uploads/temp/' . $convertedFileName);
 $command = 'ffmpeg -y -i '.$tempFile.' -b:v 5000k -b:a 380k -c:a aac -profile:a aac_low -threads 1 '.$convertedFile.'';
 exec($command);
 @File::delete($tempFile);

 try {
 $twitter = Twitter::usingCredentials($requestToken['token'], $requestToken['secret']);
 if ($file->refe_type === 'text') {
 $twitter->postTweet([
 'status' => urldecode($postContent),
 'format' => 'json',
 ]);

 $result['link'] = 'https://twitter.com/home';
 $result['status'] = true;
 $result['message'] = 'Your content successfully published on Twitter. You can visit to Twitter and check it.';
 $result['publishing_status'] = 'done';
 } else if ($file->refe_type === 'video' || $file->refe_type === 'image') {
 if ($file->refe_type === 'video') {
 $duration = getVideoDuration($file->refe_file_path);

 if ($duration > config('constant.sharing_configs.max_video_duration.twitter')) {
 throw new \Exception('The duration of the video file must not exceed 140 seconds.');
 }
 }

 $isFileTypeSupported = checkPublishedFileType('twitter', $file->refe_type, strtolower($ext));
 $isFileSizeSupported = checkPublishedFileSize('twitter', $file->refe_type, $fileSize, strtolower($ext));

 if (!$isFileTypeSupported) {
 throw new \Exception('Your content can\'t successfully published on Twitter. This file type is not supported for publishing.');
 }

 if (!$isFileSizeSupported) {
 throw new \Exception('Your content can\'t successfully published on Twitter. The file size is exceeded.');
 }

 if ($file->refe_type === 'video') $fileSize = filesize($convertedFile);

 if (strtolower($ext) === 'gif') {
 $initMedia = $twitter->uploadMedia([
 'command' => 'INIT',
 'total_bytes' => (int)$fileSize
 ]);
 } else {
 $initMedia = $twitter->uploadMedia([
 'command' => 'INIT',
 'media_type' => $mediaType,
 'media_category' => $mediaCategory,
 'total_bytes' => (int)$fileSize
 ]);
 }

 $mediaId = (int)$initMedia->media_id_string;

 $fp = fopen($convertedFile, 'r');
 $segmentId = 0;

 while (!feof($fp)) {
 $chunk = fread($fp, 1048576);

 $twitter->uploadMedia([
 'media_data' => base64_encode($chunk),
 'command' => 'APPEND',
 'segment_index' => $segmentId,
 'media_id' => $mediaId
 ]);

 $segmentId++;
 }

 fclose($fp);

 $twitter->uploadMedia([
 'command' => 'FINALIZE',
 'media_id' => $mediaId
 ]);

 if ($file->refe_type === 'video') {
 $waits = 0;

 while ($waits <= 4) {
 // Authorizing header for Twitter API
 $oauth = [
 'command' => 'STATUS',
 'media_id' => $mediaId,
 'oauth_consumer_key' => config('twitter.consumer_key'),
 'oauth_nonce' => Str::random(42),
 'oauth_signature_method' => 'HMAC-SHA1',
 'oauth_timestamp' => time(),
 'oauth_token' => $requestToken['token'],
 'oauth_version' => '1.0'
 ];

 // Generate an OAuth 1.0a HMAC-SHA1 signature for an HTTP request
 $baseInfo = $this->buildBaseString('https://upload.twitter.com/1.1/media/upload.json', 'GET', $oauth);
 // Getting a signing key
 $compositeKey = rawurlencode(config('twitter.consumer_secret')) . '&' . rawurlencode($requestToken['secret']);
 // Calculating the signature
 $oauthSignature = base64_encode(hash_hmac('sha1', $baseInfo, $compositeKey, true));
 $oauth['oauth_signature'] = $oauthSignature;
 $headers['Authorization'] = $this->buildAuthorizationHeader($oauth);

 try {
 $guzzle = new GuzzleClient([
 'headers' => $headers
 ]);
 $response = $guzzle->request( 'GET', 'https://upload.twitter.com/1.1/media/upload.json?command=STATUS&media_id=' . $mediaId);
 $uploadStatus = json_decode($response->getBody()->getContents());
 } catch (\Exception | GuzzleException $e) {
 dd($e->getMessage(), $e->getLine(), $e->getFile());
 }

 if (isset($uploadStatus->processing_info->state)) {
 switch ($uploadStatus->processing_info->state) {
 case 'succeeded':
 $waits = 5; // break out of the while loop
 break;
 case 'failed':
 File::delete($tempFile);
 Log::error('File processing failed: ' . $uploadStatus->processing_info->error->message);
 throw new \Exception('File processing failed: ' . $uploadStatus->processing_info->error->message);
 default:
 sleep($uploadStatus->processing_info->check_after_secs);
 $waits++;
 }
 } else {
 throw new \Exception('There was an unknown error uploading your file');
 }
 }
 }

 $twitter->postTweet(['status' => urldecode($postContent), 'media_ids' => $initMedia->media_id_string]);
 @File::delete($convertedFile);
 $result['link'] = 'https://twitter.com/home';
 $result['status'] = true;
 $result['message'] = 'Your content successfully published on Twitter. You can visit to Twitter and check it.';
 $result['publishing_status'] = 'done';
 }
 } catch (\Exception $e) {
 dd($e->getMessage());
 $result['message'] = $e->getMessage();
 return $result;
 }

 return $result;
 }

 /**
 * @param $baseURI
 * @param $method
 * @param $params
 * @return string
 *
 * Creating the signature base string
 */
 protected function buildBaseString($baseURI, $method, $params): string
 {
 $r = array();
 ksort($params);
 foreach($params as $key=>$value){
 $r[] = "$key=" . rawurlencode($value);
 }
 return $method . "&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $r));
 }

 /**
 * @param $oauth
 * @return string
 *
 * Collecting parameters
 */
 protected function buildAuthorizationHeader($oauth): string
 {
 $r = 'OAuth ';
 $values = array();
 foreach($oauth as $key=>$value)
 $values[] = "$key=\"" . rawurlencode($value) . "\"";
 $r .= implode(', ', $values);
 return $r;
 }
}




I would be very grateful if someone would help me.


-
MP4Box / FFMPEG concat loses audio after first clip
17 novembre 2017, par user1615343So I am certainly no expert when it comes to either of these tools, but I have a web-based project that’s executing commands on an Amazon Linux server to concatenate two video files that are uploaded.
Both files are converted to mp4s first using FFMPEG, and those play perfectly in a browser after conversion :
ffmpeg -i file1.mpg -c:v libx264 -crf 22 -c:a aac -strict -2 -movflags faststart file2.mp4
Then, I attempt to combine these two resulting mp4s into a single mp4. I tried using FFMPEG to do this but to no avail. Switching to try MP4Box got me much closer : the videos are concatenated together, but the audio stops playing at the end of the first clip, and the second clip is silent.
MP4Box -force-cat -keepsys -add file.mp4 -cat file2.mp4 out.mp4
I’ve tried varying versions of the above command with no better results. Any input is greatly appreciated.
EDIT : info on .mp4 files using
ffmpeg -i file1.mp4 -i file2.mp4
ffmpeg -i 1510189259715DogRunsintoGlassDoor_315a03a8e20acfc.mp4 -i
1510189273549NewhouseMoonMoonneverseenstairsbeforefunnydog_285a03a8e6aab25.mp4ffmpeg version N-61041-g52a2138 Copyright (c) 2000-2014 the FFmpeg
developersbuilt on Mar 2 2014 05:45:04 with gcc 4.6 (Debian 4.6.3-1)
configuration : —prefix=/root/ffmpeg-static/64bit
—extra-cflags=’-I/root/ffmpeg-static/64bit/include -static’ —extra-ldflags=’-L/root/ffmpeg-static/64bit/lib -static’ —extra-libs=’-lxml2 -lexpat -lfreetype’ —enable-static —disable-shared —disable-ffserver —disable-doc —enable-bzlib —enable-zlib —enable-postproc —enable-runtime-cpudetect —enable-libx264 —enable-gpl —enable-libtheora —enable-libvorbis —enable-libmp3lame —enable-gray —enable-libass —enable-libfreetype —enable-libopenjpeg —enable-libspeex —enable-libvo-aacenc —enable-libvo-amrwbenc —enable-version3 —enable-libvpxlibavutil 52. 66.100 / 52. 66.100
libavcodec 55. 52.102 / 55. 52.102
libavformat 55. 33.100 / 55. 33.100
libavdevice 55. 10.100 / 55. 10.100
libavfilter 4. 2.100 / 4. 2.100
libswscale 2. 5.101 / 2. 5.101
libswresample 0. 18.100 / 0. 18.100
libpostproc 52. 3.100 / 52. 3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from
’1510189259715DogRunsintoGlassDoor_315a03a8e20acfc.mp4’ :Metadata :
major_brand : isom
minor_version : 512
compatible_brands : isomiso2avc1mp41
encoder : Lavf55.33.100
Duration : 00:00:04.92, start : 0.023220, bitrate : 634 kb/s
Stream #0:0(und) : Video : h264 (High) (avc1 / 0x31637661), yuv420p,
360x360 [SAR 1:1 DAR 1:1], 501 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc
(default)Metadata :
handler_name : VideoHandler
Stream #0:1(und) : Audio : aac (mp4a / 0x6134706D), 44100 Hz, mono,
fltp, 132 kb/s (default)Metadata :
handler_name : SoundHandler
Input #1, mov,mp4,m4a,3gp,3g2,mj2, from
’1510189273549NewhouseMoonMoonneverseenstairsbeforefunnydog_285a03a8e6aab25.mp4’ :Metadata :
major_brand : isom
minor_version : 512
compatible_brands : isomiso2avc1mp41
encoder : Lavf55.33.100
Duration : 00:00:18.79, start : 0.023220, bitrate : 455 kb/s
Stream #1:0(und) : Video : h264 (High) (avc1 / 0x31637661), yuv420p,
362x360 [SAR 1:1 DAR 181:180], 320 kb/s, 29.94 fps, 29.94 tbr, 11976
tbn, 59.88 tbc (default)Metadata :
handler_name : VideoHandler
Stream #1:1(eng) : Audio : aac (mp4a / 0x6134706D), 44100 Hz, stereo,
fltp, 129 kb/s (default)Metadata :
handler_name : SoundHandler
At least one output file must be specified
-
Reason for write EPIPE error in my implentation ?
18 mai 2019, par Chrisl446So I currently have a small node.js express application for uploading images using sharp & thumbnails created from .mp4 videos using simple-thumbnail package/ffmpeg.
The app works perfectly when uploading an image, the file is uploaded sharp processes it, then passes it along and it ends up in my amazon s3 bucket as expected. No errors what so ever.
However, when I upload an mp4 video that I use to create and upload a thumbnail from by using simple-thumbnails genThumbnail() function, which uses ffmpeg child process, the thumbnail uploads successully to my s3 bucket, HOWEVER my app returns an EPIPE write error and NOT the url of the uploaded files url on S3.
What is causing this and how can I fix it, considering it’s pretty much working aside from the EPIPE error that is being returned ? Thanks ahead !
The packages of concern used are as follows :
multer-s3 <- this one with the transform option, not the standard multer-s3 package
const express = require('express');
const app = express();
const aws = require('aws-sdk');
const multer = require('multer');
const multerS3 = require('multer-s3'); //github:gmenih341/multer-s3 version of multer-s3 with transform option
const sharp = require('sharp');
const genThumbnail = require('simple-thumbnail');
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Orgin, X-Requested-With, Content-Type, Accept, Authorization');
if (req.method === 'OPTIONS') {
res.header('Access-Control-Allow-Methods', 'POST');
return res.status(200).json({});
}
next();
});
let uniqueFileName;
let s3BucketName = 'bucketname';
let s3 = new aws.S3({
accessKeyId: ACCESS_KEY,
secretAccessKey: SECRET_KEY,
Bucket: s3BucketName
});
let upload = multer({
storage: multerS3({
s3: s3,
bucket: s3BucketName,
acl: 'public-read',
cacheControl: 'max-age=31536000',
contentType: multerS3.AUTO_CONTENT_TYPE,
shouldTransform: true,
transforms: [{
id: 'thumbnail',
key: function (req, file, cb) {
uniqueFileName = Date.now().toString();
cb(null, uniqueFileName + '.jpg')
},
transform: function (req, file, cb) {
if (file.mimetype == 'video/mp4') {
//When using simple-thumbnails' getThumbnail() on an mp4 video it uploads succesfully to S3 but node returns EPIPE write error
cb(null, genThumbnail(null, null, '250x?'))
} else {
//When using sharp to resize an image this works perfectly and retuns the JSON below with the files S3 URL
cb(null, sharp().jpeg())
}
}
}]
})
});
app.post('/upload', upload.array('theFile'), (req, res) => {
res.json({
fileS3Url: 'https://s3.amazonaws.com/'+ s3BucketName +'/' + uniqueFileName
});
});
app.use((req, res, next) => {
const error = new Error('Not found');
error.status = 404;
next(error);
});
app.use((error, req, res, next) => {
res.status(error.status || 500);
res.json({
error: {
message: error.message
}
});
});
module.exports = app;