
Recherche avancée
Médias (1)
-
Richard Stallman et le logiciel libre
19 octobre 2011, par
Mis à jour : Mai 2013
Langue : français
Type : Texte
Autres articles (71)
-
Websites made with MediaSPIP
2 mai 2011, parThis page lists some websites based on MediaSPIP.
-
List of compatible distributions
26 avril 2011, parThe table below is the list of Linux distributions compatible with the automated installation script of MediaSPIP. Distribution nameVersion nameVersion number Debian Squeeze 6.x.x Debian Weezy 7.x.x Debian Jessie 8.x.x Ubuntu The Precise Pangolin 12.04 LTS Ubuntu The Trusty Tahr 14.04
If you want to help us improve this list, you can provide us access to a machine whose distribution is not mentioned above or send the necessary fixes to add (...) -
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 (9670)
-
FFMpeg Coding in C : Encoder returns EOF at first interaction. Encoder not opened correctly ? [closed]
26 février, par Davidhoheyas I'm fairly new to FFMpeg Programming and C in general, the code looks like a mess.


I have smashed my head against a wall trying to get this code to work for about a week.


int decode_encode_pipeline(AVFormatContext *Input_Format_Context, AVFormatContext *Output_Format_Context, int *streams_list){

 const AVCodec *DECodec, *ENCodec;
 AVCodecContext *DECodecContext = NULL, *ENCodecContext = NULL;
 AVCodecParameters *CodecParameters = NULL;
 AVDictionary *opts = NULL;
 AVPacket *Packet;
 AVFrame *Frame;
 int check;

 Packet = av_packet_alloc();
 if(!Packet){
 
 printf("\nFehler bei Allocating Packet");
 
 return 0;
 
 }

 Frame = av_frame_alloc();
 if(!Frame){
 
 printf("\nFehler bei Allocating Frame");
 
 return 0;
 
 }

 CodecParameters = Input_Format_Context->streams[Packet->stream_index]->codecpar;
 if(!CodecParameters){

 printf("\nCodecParameters konnte nicht erstellt oder zugewiesen werden.");

 }

 DECodec = avcodec_find_decoder(CodecParameters->codec_id);
 if(!DECodec){
 
 printf("\nCodec nicht gefunden");
 
 return 0;
 
 }

 DECodecContext = avcodec_alloc_context3(DECodec);
 if (!DECodecContext){
 
 printf("\nFehler bei Allocating CodecContext");
 
 return 0;
 
 }

 ENCodec = avcodec_find_encoder(CodecParameters->codec_id);
 if(!DECodec){
 
 printf("\nCodec nicht gefunden");
 
 return 0;
 
 }

 ENCodecContext = avcodec_alloc_context3(ENCodec);
 if (!ENCodecContext){
 
 printf("\nFehler bei Allocating CodecContext");
 
 return 0;
 
 }

 check = avformat_write_header(Output_Format_Context, &opts);
 if(check < 0){

 printf("\nFehler beim Öffnen des Output Files.");
 
 return 1;

 }

 avcodec_parameters_to_context(DECodecContext, CodecParameters);
 avcodec_parameters_to_context(ENCodecContext, CodecParameters);

 ENCodecContext->width = DECodecContext->width;
 ENCodecContext->height = DECodecContext->height;
 ENCodecContext->bit_rate = DECodecContext->bit_rate;
 ENCodecContext->time_base = (AVRational){1, 30};
 ENCodecContext->framerate = DECodecContext->framerate;
 ENCodecContext->gop_size = DECodecContext->gop_size;
 ENCodecContext->max_b_frames = DECodecContext->max_b_frames;
 ENCodecContext->pix_fmt = DECodecContext->pix_fmt;
 if(ENCodec->id == AV_CODEC_ID_H264){

 av_opt_set(ENCodecContext->priv_data, "preset", "slow", 0);

 }

 check = avcodec_open2(DECodecContext, DECodec, NULL);
 if(check < 0){
 
 printf("\nFehler bei Öffnen von DECodec");
 
 return 1;
 
 }

 check = avcodec_open2(ENCodecContext, ENCodec, NULL);
 if(check < 0){
 
 printf("\nFehler bei Öffnen von ENCodec");
 
 return 1;
 
 }

 while(1){
 
 check = av_read_frame(Input_Format_Context, Packet);
 if(check < 0){
 
 break;
 
 }

 AVStream *in_stream, *out_stream;

 in_stream = Input_Format_Context->streams[Packet->stream_index];
 out_stream = Output_Format_Context->streams[Packet->stream_index];

 if(in_stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && Packet->stream_index == streams_list[Packet->stream_index]){

 check = avcodec_send_packet(DECodecContext, Packet);
 if(check < 0){

 printf("\nFehler bei Encoding");

 return 1;

 }

 AVPacket *EncodedPacket;
 EncodedPacket = av_packet_alloc();
 if(!EncodedPacket){
 
 printf("\nFehler bei Allocating Packet");
 
 return 1;
 
 }

 /*While Loop Decoding*/
 while(check >= 0){
 
 check = avcodec_receive_frame(DECodecContext, Frame);
 if(check == AVERROR(EAGAIN)){
 
 continue;
 
 }else if(check == AVERROR_EOF){
 
 break;
 
 }else if(check < 0){
 
 printf("\nFehler bei Decoding");
 
 return 1;
 
 }

 /*Convert Colorspace*/
 struct SwsContext *SwsContexttoRGB = sws_getContext(Frame->width, Frame->height, Frame->format, Frame->width, Frame->height, AV_PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL);
 struct SwsContext *SwsContexttoOriginal = sws_getContext(Frame->width, Frame->height, AV_PIX_FMT_RGB24, Frame->width, Frame->height, Frame->format, SWS_BILINEAR, NULL, NULL, NULL);
 if(!SwsContexttoRGB || !SwsContexttoOriginal){

 printf("\nSwsContext konnte nicht befüllt werden.");

 return 1;

 } 

 if(Frame->linesize < 0){

 printf("\nFehler: linesize ist negativ und nicht kompatibel\n");

 return 1;

 }

 AVFrame *RGBFrame;
 RGBFrame = av_frame_alloc();
 if(!RGBFrame){

 printf("\nFehler bei der Reservierung für den RGBFrame");

 return 1;

 }
 /*
 int number_bytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, Frame->width, Frame->height, 1);
 if(number_bytes < 0){

 printf("\nFehler bei der Berechnung der benoetigten Bytes fuer Konvertierung");

 return 1;

 }
 
 uint8_t *rgb_buffer = (uint8_t *)av_malloc(number_bytes*sizeof(uint8_t));
 if(rgb_buffer == NULL){

 printf("\nFehler bei der Reservierung für den RGBBuffer");

 return 1;

 }

 check = av_image_fill_arrays(RGBFrame->data, RGBFrame->linesize, rgb_buffer, AV_PIX_FMT_RGB24, Frame->width, Frame->height, 1);
 if(check < 0){

 printf("\nFehler bei der Zuweisung der RGB Daten");

 return 1;

 }*/

 //sws_scale(SwsContexttoRGB, (const uint8_t * const *)Frame->data, Frame->linesize, 0, Frame->height, RGBFrame->data, RGBFrame->linesize);
 sws_scale_frame(SwsContexttoRGB, Frame, RGBFrame);
 printf("\nIch habe die Daten zu RGB konvertiert.");

 //sws_scale(SwsContexttoOriginal, (const uint8_t * const *)RGBFrame->data, RGBFrame->linesize, 0, Frame->height, Frame->data, Frame->linesize);
 sws_scale_frame(SwsContexttoOriginal, RGBFrame, Frame);
 printf("\nIch habe die Daten zurück ins Original konvertiert.");

 Frame->format = ENCodecContext->pix_fmt;
 Frame->width = ENCodecContext->width;
 Frame->height = ENCodecContext->height;
 
 check = av_frame_get_buffer(Frame, 0);
 if(check < 0){
 
 printf("\nFehler bei Allocating Frame Buffer");
 
 return 1;
 
 }

 /* Encoding */
 check = av_frame_make_writable(Frame);
 if(check < 0){

 printf("\nFehler bei Make Frame Writable");

 return 1;

 }

 encode(ENCodecContext, Frame, EncodedPacket, Output_Format_Context);

 sws_freeContext(SwsContexttoRGB);
 sws_freeContext(SwsContexttoOriginal);
 av_frame_free(&RGBFrame);
 //av_free(rgb_buffer);

 }

 /* Flushing Encoder */
 encode(ENCodecContext, NULL, EncodedPacket, Output_Format_Context);

 //avcodec_flush_buffers(DECodecContext);
 //avcodec_flush_buffers(ENCodecContext);

 av_packet_free(&EncodedPacket);

 }else{

 av_interleaved_write_frame(Output_Format_Context, Packet);

 }

 }

 av_write_trailer(Output_Format_Context); 

 /* Memory Free */
 avcodec_free_context(&DECodecContext);
 avcodec_free_context(&ENCodecContext);
 avcodec_parameters_free(&CodecParameters);
 av_frame_free(&Frame);
 av_packet_free(&Packet);

 return 0;

}




The function encode looks as follows :


static void encode(AVCodecContext *ENCodecContext, AVFrame *Frame, AVPacket *EncodedPacket, AVFormatContext *Output_Format_Context){

 int check;



 check = avcodec_send_frame(ENCodecContext, Frame);
 if(check == AVERROR(EAGAIN)){
 printf("\nEAGAIN");
 } 
 if(check == AVERROR_EOF){
 printf("\nEOF");
 }
 if(check == AVERROR(EINVAL)){
 printf("\nEINVAL");
 }
 if(check == AVERROR(ENOMEM)){
 printf("\nENOMEM");
 }
 if(check < 0){

 printf("\nFehler bei Encoding Send Frame. Check = %d", check);

 return;

 }

 while(check >= 0){

 check = avcodec_receive_packet(ENCodecContext, EncodedPacket);
 if(check == AVERROR(EAGAIN) || check == AVERROR_EOF){

 return;

 }else if(check < 0){

 printf("\nFehler bei Encoding");

 return;

 }

 if (av_interleaved_write_frame(Output_Format_Context, EncodedPacket) < 0) {

 printf("\nFehler beim Muxen des Paketes.");
 break;

 }

 av_packet_unref(EncodedPacket);

 }

 return;

}



The program should decode a video into the individual frames convert them to RGB24, so I can work with the raw data of the frame, then convert it back to the original format and encode the frames.


The encoder doesn't play nice, as I get an EOF error at avcodec_send_frame().
But I couldn't figure it out why the encoder behaves like this.
And yes I have read the docs and example files, but either I'm massivly missing a crucial detail or I'm just ****.


Any and all help will be and is massivly appreciated.


PS. : The used libraries are libavutil, libavformat, libavcodec, libswscale. All installed with the "-dev" suffix through linux commandline. Should all be the version 7.0 libraries.


Thanks in advance.
With best regards.


- 

- Read the docs
- Shifting the encoding step out of the decoding while loop






-
How to measure the performance of a newsletter (or any email) with Piwik
19 décembre 2017, par InnoCraft — CommunityTo be able to grow your business, it is crucial to track all your marketing efforts. This includes all newsletters and emails that you share with people outside of your business. Otherwise, you won’t be able to know which of your daily efforts are yielding results.
Are you wondering if it is possible to track the performance of an emailing campaign in Piwik efficiently ? Would you like to know if it is technically easy ? No worries, here is a “How to” tutorial showing you how easily you can track an emailing in Piwik properly.
Different tracking levels for different needs
There are many things that you may be interested to track, for example :
- How many users opened your email
- How many users interacted with the links in your email
- How many users interacted on your website through your email
Let’s have a look at each of these levels.
Step 1 – Tracking email and newsletter openings in Piwik
Tracking email openings requires to add an HTML code to your newsletter. It works through what we call a tracking pixel, a tiny image of 1×1 that is transparent so the user will not be able to see it.
In order to install it, here is an example of what this code looks like :<img src="https://piwik.example.com/piwik.php?idsite=YOUR_PIWIK_WEBSITE_ID&rec=1&bots=1&url=https%3A%2F%2Fexample.com%2Femail-opened%2Fnewsletter_XYZ&action_name=Email%20opened&_rcn=internal%20email%20name&_rck=newsletter_XYZ" style="border:0;” alt="" />
The Piwik tracking pixel explained
The above URL is composed of the following URL parameters which are part of our Tracking API :
- idsite : Corresponds to the ID of the website you would like to track.
- rec : You need to have rec=1 in order for the request to be actually recorded.
- bots : Set it to 1 to include all the connections made to this request, bots included.
- url : corresponds to the URL you would like to display in Piwik every time the email is opened.
- action_name : This is the page name you would like to be tracked when the email is opened.
- _rcn : The name you would like to give to your campaign.
- _rck : The keyword you may like to use in order to summarize the content of your newsletter.
You may have noticed some special characters here such as “%20”, “%2F”. That’s because the URL is encoded. We strongly recommend you to do so in order for your tracking not to break. Many tools are available on the web in order to encode your URLs such as https://www.urlencoder.org/.
If you would like to access the previous tracking code easily, keep in mind that you can always find the tracking code generator within the “Piwik admin panel → Tracking code” :
You can find more information about it on our guide at : How do I track how many users open and read my newsletter emails (using a pixel / beacon) ?
As a result, the information will be pushed as following for any user who opens your email :
To not bias your regular page views on your website with newsletter openings, we recommend tracking newsletter openings into a new website.
Tracking even more data : the user ID example
You can go deeper in your URL tracking by inserting other parameters such as the user id if you have this information within your emailing database. One of the main benefit of tracking the User ID is to connect data across multiple devices and browsers for a given user.
You only need to add the following parameter &uid=XXX where XXX equals the dynamic value of the user ID :
Make sure that UID from your emailing provider is the same as the one used on your website in order for your data to be consistent.
Important note : some email providers are loading email messages by default which results in an opening even if the user did not actually open the email.
Step 2 – Measure the clicks within your emailing
Tracking clicks within an email lets you know with which content readers interacted the most. We recommend tracking all links in all your emails as a campaign, whether it is a newsletter, a custom support email, an email invoice, etc. You might be surprised to see which of your emails lead to conversions and if they don’t, try to tweak those emails, so they might in the future.
Tracking clicks This works thanks to URL campaign tracking. In order to perform this action, you will need to add Piwik URL parameters to all your existing link URLs :
- Website URL : for example “www.your-website.com”.
- Campaign name : for example “pk_campaign=emailing”. Represents the name you would like to give to your campaign.
- Campaign keyword : for example “pk_keyword=name-of-your-article”. Represents the name you would like to give to your content.
- Campaign source : for example “pk_source=newsletter”. Represents the name of the referrer.
- Campaign medium : for example “pk_medium=email”. Represents the type of referrer you are using.
- Campaign content : for example “pk_content=title”. Represents the type of content.
You can find more information about campaign url tracking in our “Tracking marketing campaigns with Piwik” guide.
Here is a sample showing you how you can differentiate some links in a newsletter, all pointing to the same URL :
Once you have added these URL parameters to each of your link, Piwik will clearly indicate the referrer of this specific campaign when a user clicks on a link in the newsletter and visits your website.
Important note : if you do not track your campaigns, it will result in a bad interpretation of your data within Piwik as you will get webmail services or direct entries as referrer instead of your newsletter campaign.
Step 3 – Measure emailing performances on your website
Thanks to Piwik URL campaign parameters, you can now clearly identify the traffic brought through your emailing. You can now specifically isolate users who come from emails by creating a segment :
Once done, you can either have a look at each user specifically through the visitor log report or analyze it as a whole within the rest of the reports.
You can even measure your return on investment directly if goals have been defined. In order to know more about how to track goals within Piwik.
Did you like this article ?
If you enjoyed reading this article, do not hesitate to share it around you. Moreover, if there are any topics you would like to write us about in particular, just drop us an email and we will be more than happy to write about it.
-
Write EPIPE after upgrade NodeJS
28 juillet, par RougherI am using this code for detecting audio replay gain. It was working well with NodeJs 16, but after upgrading to NodeJs 22, it started crashing a few times in an hour with this error :


write EPIPE
 at WriteWrap.onWriteComplete [as oncomplete] (node:internal/stream_base_commons:87:19) {
 errno: -32,
 code: 'EPIPE',
 syscall: 'write'
}



My original code was


static getReplayGainVolume(audioData: Buffer) {
 // Calculate the mean volume of the audio file at the given filePath
 var ffmpeg = spawn('ffmpeg', [
 '-i', '-',
 '-af', 'replaygain',
 '-f', 'null', '/dev/null',
 '-hide_banner', '-nostats'
 ]);

 var output = '';

 ffmpeg.stdin.write(audioData);
 ffmpeg.stdin.end();

 return new Promise((resolve,reject)=>{
 ffmpeg.on('error', function (err: any) {
 reject(err);
 });
 
 ffmpeg.on('close', function (_code: any) {
 // [Parsed_replaygain_0 @ 0000000002a2b5c0] track_gain = +6.53 dB
 if (!output.includes("track_gain")) {
 reject(output);

 return;
 }

 const gainWithDb = output.split("track_gain = ")[1];
 if (!gainWithDb) {
 reject(output);

 return;
 }

 const gain = gainWithDb.split(" dB")[0];
 if (!gain) {
 reject(output);

 return;
 }

 resolve(parseFloat(gain));
 });
 
 ffmpeg.stderr.on('data', function (data: any) {
 // ffmpeg sends all output to stderr. It is not a bug, it is a feature :)
 var tData = data.toString('utf8');
 output += tData;
 });
 });
 }



Then after search in forums and Google, I improved (I hope I improved it with cleanups)


static getReplayGainVolume(audioData: Buffer): Promise<number> {
 return new Promise((resolve, reject) => {
 const FFMPEG_PATH = 'ffmpeg'; // Adjust this if ffmpeg is not in system PATH
 const FFMPEG_TIMEOUT_MS = 30 * 1000; // 30 seconds timeout for FFmpeg execution

 let ffmpeg: ChildProcessWithoutNullStreams;
 let output = ''; // Accumulate all stderr output

 // Timeout for the FFmpeg process itself
 const ffmpegTimeout = setTimeout(() => {
 log.error(`[FFmpeg] FFmpeg process timed out after ${FFMPEG_TIMEOUT_MS / 1000} seconds. Killing process.`);
 if (ffmpeg && !ffmpeg.killed) {
 ffmpeg.kill('SIGKILL'); // Force kill
 reject(new Error(`FFmpeg process timed out and was killed.`));
 }
 }, FFMPEG_TIMEOUT_MS);

 // --- Define cleanup function to be called on process exit/error ---
 const cleanup = (shouldReject = false, error?: Error | string) => {
 clearTimeout(ffmpegTimeout); // Ensure timeout is cleared

 // Remove all listeners to prevent leaks
 // This is CRITICAL for long-running bots that spawn many child processes
 ffmpeg.stdin.removeAllListeners();
 ffmpeg.stdout.removeAllListeners();
 ffmpeg.stderr.removeAllListeners();
 ffmpeg.removeAllListeners(); // Remove process listeners

 if (ffmpeg && !ffmpeg.killed) { // Ensure ffmpeg process is killed if still alive
 ffmpeg.kill(); // Graceful kill (SIGTERM), then wait for exit. If not, then SIGKILL.
 }

 if (shouldReject) {
 reject(error instanceof Error ? error : new Error(String(error)));
 }
 };

 try {
 ffmpeg = spawn(FFMPEG_PATH, [
 '-i', 'pipe:0', // Read input from stdin (pipe:0)
 '-af', 'replaygain',
 '-f', 'null', '/dev/null', // Write output to null device (discard audio output)
 '-hide_banner', '-nostats' // Suppress ffmpeg's initial info and progress stats
 ], { stdio: ['pipe', 'pipe', 'pipe'] }); // Explicitly pipe stdin, stdout, stderr

 // --- CRITICAL: Event Handlers for ffmpeg process ---

 // 1. Handle errors during spawning or execution (e.g., ffmpeg not found)
 ffmpeg.on('error', (err: any) => {
 log.error(`[FFmpeg] Failed to spawn or execute FFmpeg process:`, err);
 cleanup(true, new Error(`FFmpeg process error: ${err.message}`));
 });

 // 2. Accumulate stderr output (where replaygain results and ffmpeg errors are printed)
 ffmpeg.stderr.on('data', (data: Buffer) => {
 output += data.toString('utf8');
 });

 // 3. Handle process exit (success or failure)
 ffmpeg.on('close', (code: number) => { // 'close' indicates process has exited
 log.debug(`[FFmpeg] FFmpeg process exited with code: ${code}.`);
 if (code !== 0) { // Non-zero exit code means failure
 log.error(`[FFmpeg] FFmpeg process exited with non-zero code ${code}. Output:\n${output}`);
 cleanup(true, new Error(`FFmpeg process failed with exit code ${code}. Output: ${output}`));
 return;
 }

 // If successful exit (code 0), parse the output
 if (!output.includes("track_gain")) {
 log.error(`[FFmpeg] 'track_gain' not found in FFmpeg output (exit code 0). Output:\n${output}`);
 cleanup(true, new Error(`'track_gain' not found in FFmpeg output. Output: ${output}`));
 return;
 }

 try {
 // Regex to parse track_gain (e.g., "+6.53 dB" or "-12.00 dB")
 const gainMatch = output.match(/track_gain\s*=\s*([+-]?\d+\.?\d*)\s*dB/);
 if (gainMatch && gainMatch[1]) {
 const gain = parseFloat(gainMatch[1]);
 log.debug(`[FFmpeg] Replay gain volume: ${gain} dB.`);
 cleanup(); // Clean up on success
 resolve(gain);
 } else {
 log.error(`[FFmpeg] Failed to parse gain from FFmpeg output. Output:\n${output}`);
 cleanup(true, new Error(`Failed to parse gain from FFmpeg output. Output: ${output}`));
 }
 } catch (parseError: any) {
 log.error(`[FFmpeg] Error parsing FFmpeg replay gain output:`, parseError);
 cleanup(true, new Error(`Error parsing FFmpeg output: ${parseError.message}. Output: ${output}`));
 }
 });

 // 4. Write audio data to ffmpeg's stdin
 // This is the only write operation that could throw EPIPE in this function.
 try {
 ffmpeg.stdin.write(audioData);
 ffmpeg.stdin.end(); // Close stdin to signal end of input
 } catch (stdinError: any) {
 log.error(`[FFmpeg] Error writing audioData to FFmpeg stdin:`, stdinError);
 // This error means ffmpeg's stdin pipe closed unexpectedly.
 // This is the direct equivalent of an EPIPE (Broken Pipe) at the child process level.
 cleanup(true, new Error(`Failed to pipe audio data to FFmpeg stdin: ${stdinError.message}`));
 }

 } catch (spawnError: any) { // Catch errors from the spawn call itself (e.g., FFMPEG_PATH is invalid)
 log.error(`[FFmpeg] Error spawning FFmpeg:`, spawnError);
 cleanup(true, new Error(`Failed to spawn FFmpeg process: ${spawnError.message}`));
 }
 });
 }
</number>


But unfortunately I still get the same error. Has anyone encountered this problem ? How can I solve it ?


I use ffmpeg version 4.2.7-0ubuntu0.1


Thanks.