Recherche avancée

Médias (1)

Mot : - Tags -/Rennes

Autres articles (46)

  • Les autorisations surchargées par les plugins

    27 avril 2010, par

    Mediaspip core
    autoriser_auteur_modifier() afin que les visiteurs soient capables de modifier leurs informations sur la page d’auteurs

  • Les tâches Cron régulières de la ferme

    1er décembre 2010, par

    La gestion de la ferme passe par l’exécution à intervalle régulier de plusieurs tâches répétitives dites Cron.
    Le super Cron (gestion_mutu_super_cron)
    Cette tâche, planifiée chaque minute, a pour simple effet d’appeler le Cron de l’ensemble des instances de la mutualisation régulièrement. Couplée avec un Cron système sur le site central de la mutualisation, cela permet de simplement générer des visites régulières sur les différents sites et éviter que les tâches des sites peu visités soient trop (...)

  • Other interesting software

    13 avril 2011, par

    We don’t claim to be the only ones doing what we do ... and especially not to assert claims to be the best either ... What we do, we just try to do it well and getting better ...
    The following list represents softwares that tend to be more or less as MediaSPIP or that MediaSPIP tries more or less to do the same, whatever ...
    We don’t know them, we didn’t try them, but you can take a peek.
    Videopress
    Website : http://videopress.com/
    License : GNU/GPL v2
    Source code : (...)

Sur d’autres sites (8946)

  • stream_encoder.c : Fix compiler warning

    13 décembre 2015, par Erik de Castro Lopo
    stream_encoder.c : Fix compiler warning
    

    Remove incorrect assignment to `encoder->protected_->state`.

    • [DH] src/libFLAC/stream_encoder.c
  • How to fix here "EPIPE" in Node js Socket.io

    23 avril, par Mehdi008

    Receiving this error :

    


    Error: write EPIPE
        at afterWriteDispatched (node:internal/stream_base_commons:161:15)
        at writeGeneric (node:internal/stream_base_commons:152:3)
        at Socket._writeGeneric (node:net:958:11)
        at Socket._write (node:net:970:8)
        at doWrite (node:internal/streams/writable:598:12)
        at clearBuffer (node:internal/streams/writable:783:7)
        at onwrite (node:internal/streams/writable:653:7)
        at WriteWrap.onWriteComplete [as oncomplete] (node:internal/stream_base_commons:107:10)
    Emitted 'error' event on Socket instance at:
        at emitErrorNT (node:internal/streams/destroy:169:8)
        at emitErrorCloseNT (node:internal/streams/destroy:128:3)
        at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
      errno: -4047,
      code: 'EPIPE',
      syscall: 'write'
    }


    


    // for this code: const { spawn } = require("child_process");

module.exports = (socket, pool) => {
    
    let stream_req_token = "";
    let rtmps_array = [];

    socket.on("stream_request_token",async(token)=>{

        const stream_reqs = await pool`SELECT * FROM stream_request WHERE token=${token}`;


        if(stream_reqs.length === 0){
            
            socket.emit("token_validation_response",false);
            return;
        }

        const stream_req = stream_reqs[0];

        if(!stream_req.is_valid){

            socket.emit("token_validation_response",false);
            return;
        }

        socket.emit("token_validation_response",true);

        stream_req_token = token;


    })

    socket.on("rtmps_array",async(array)=>{

        try{

            const rtmps = JSON.parse(array);

        const streams_requests = await pool`SELECT id FROM stream_request WHERE token=${stream_req_token}`;
        const stream_req_id = streams_requests[0].id;

        rtmps_array = rtmps;

        rtmps.map(async(rtmp)=>{

            await pool`INSERT INTO stream (platform,url,url_key,stream_request_id) 
            VALUES(${rtmp.platform},${rtmp.url},${rtmp.key},${stream_req_id})`;
        })

        socket.emit("rtmps_array_response",true);

        } catch(err){

            console.log(err);
            socket.emit("rtmps_array_response",false);

        }


    })

    //Start Streaming
    let ffmpegProcess = null;
    let isStreaming = false; // Flag to track streaming state

  socket.on("stream", (chunk) => {
    if (!ffmpegProcess) {
        console.log('Initializing FFmpeg process...');

        // Spawn FFmpeg process
        const resolution = "1280x720"; // Change to "1920x1080" for 1080p

        const ffmpegArgs = [
            "-i", "pipe:0", // Input from stdin
            "-c:v", "libx264", // Video codec
            "-preset", "veryfast", // Low latency encoding
            "-b:v", "4500k", // Target average bitrate (4.5 Mbps)
            "-minrate", "2500k", // Minimum bitrate
            "-maxrate", "6000k", // Maximum bitrate
            "-bufsize", "16000k", // Buffer size (twice the max bitrate)
            "-r", "30", // **FORCE 30 FPS**
            "-g", "60", // Keyframe interval (every 2 seconds)
            "-tune", "zerolatency", // Low latency tuning
            "-sc_threshold", "0", // Constant bitrate enforcement
            "-flags", "+global_header",
          
            // **Resolution Fix**
            "-s", resolution, // **Set resolution to 720p or 1080p**
            "-aspect", "16:9", // **Maintain aspect ratio**
            
            // **Frame Rate Fix**
            "-vsync", "cfr", // **Forces Constant Frame Rate (CFR)**
            "-fps_mode", "cfr", // **Prevents FFmpeg from auto-adjusting FPS**
            
            // Audio settings
            "-c:a", "aac",
            "-b:a", "128k", // Audio bitrate
            "-ar", "44100", // Audio sample rate
            "-ac", "2", // Stereo audio
          
            "-f", "flv" // Output format
          ];
      
          // Map the streams to multiple RTMP destinations
          rtmps_array.forEach((rtmp) => {
            ffmpegArgs.push("-map", "0:v:0", "-map", "0:a:0", "-f", "flv", `${rtmp.url}/${rtmp.key}`);
          });
      
          // Spawn FFmpeg process
          ffmpegProcess = spawn("ffmpeg", ffmpegArgs);

        ffmpegProcess.stderr.on('data', (data) => {
            console.log(`FFmpeg STDERR: ${data}`);
    });

        ffmpegProcess.on('close', (code) => {
            console.log(`FFmpeg process closed with code ${code}`);
            ffmpegProcess = null; // Reset process
            isStreaming = false; // Reset streaming state
        });

        ffmpegProcess.on('error', (err) => {
            console.error(`FFmpeg process error: ${err.message}`);
            ffmpegProcess = null; // Reset process
            isStreaming = false; // Reset streaming state
        });

        console.log('FFmpeg process started.');
        isStreaming = true; // Set streaming state to true
    }

    // Write chunk to FFmpeg process
    if (isStreaming && ffmpegProcess && ffmpegProcess.stdin && !ffmpegProcess.stdin.destroyed) {
        try {
            ffmpegProcess.stdin.write(chunk); // Write chunk to stdin
            console.log('Chunk written to FFmpeg.');
        } catch (err) {
            console.error('Error writing chunk to FFmpeg stdin:', err.message);
        }
    } else {
        console.error('FFmpeg process or stdin is not ready.');
    }
});

socket.on("stop-stream", async() => {
    console.log('Stream Stopped.');

    if(stream_req_token.length !== 0){

        await pool`UPDATE stream_request 
               SET is_valid=false
               WHERE token=${stream_req_token}`

        await pool`DELETE FROM current_streams WHERE id=${stream_req_token}`;       
    }

    if (ffmpegProcess) {
        isStreaming = false; // Set streaming state to false

        try {
            // Check if stdin is open before closing
            if (ffmpegProcess.stdin) {
                ffmpegProcess.stdin.end(); // End stdin safely
            }

            // Wait for FFmpeg to close before setting to null
            ffmpegProcess.on("close", () => {
                console.log("FFmpeg process closed.");
                ffmpegProcess = null;
            });

            // Kill FFmpeg process
            ffmpegProcess.kill("SIGTERM"); // Use SIGTERM for graceful exit

        } catch (err) {
            console.error("Error while stopping FFmpeg:", err.message);
        }
    } else {
        console.log("No active FFmpeg process.");
    }
});


socket.on('error', (err) => {
  console.error('Socket error:', err);
});

socket.on("disconnect", async() => {
    console.log('Client Disconnected.');

    if(stream_req_token.length !== 0){

        await pool`UPDATE stream_request 
               SET is_valid=false
               WHERE token=${stream_req_token}`;

        await pool`DELETE FROM current_streams WHERE id=${stream_req_token}`;       

    }
    
    if (ffmpegProcess) {
        isStreaming = false; // Set streaming state to false

        try {
            // Check if stdin is open before closing
            if (ffmpegProcess.stdin) {
                ffmpegProcess.stdin.end(); // End stdin safely
            }

            // Wait for FFmpeg to close before setting to null
            ffmpegProcess.on("close", () => {
                console.log("FFmpeg process closed.");
                ffmpegProcess = null;
            });

            // Kill FFmpeg process
            ffmpegProcess.kill("SIGTERM"); // Use SIGTERM for graceful exit


        } catch (err) {
            console.error("Error while stopping FFmpeg:", err.message);
        }
    } else {
        console.log("No active FFmpeg process.");
    }
});

};


    


    


  • Gstreamer convert and display video v4l2 - tee problems in rust

    27 mars 2023, par d3im

    I have USB grabber v4l2 source and I want to tee stream to autovideosink and x264enc to file (now as fake black hole)

    


    When I disable one or another branch it works but together Pipeline goes :

    


    Pipeline state changed from Null to Ready
Pipeline state changed from Ready to Paused


    


    and stays there never switches to Playing

    


    gst-launch-1.0 with similar functionality works well.

    


        gst::Element::link_many(&[&pw_video, &v_caps, &vid_queuey, &vid_tee]).unwrap();
    gst::Element::link_many(&[&vid_queue1, &autovideoconvert, &vid_queuex, &autovideosink]).unwrap();
    gst::Element::link_many(&[&vid_queue2, &autovideoconvert_x264, &vid_queue3, &x264, &vid_queue4, &fake]).unwrap();

    let tee_display_pad = vid_tee.request_pad_simple("src_10").unwrap();
    let vid_queue1_pad = vid_queue1.static_pad("sink").unwrap();

    tee_display_pad.link(&vid_queue1_pad).unwrap();

    let tee_convert_pad = vid_tee.request_pad_simple("src_20").unwrap();
    let vid_queue2_pad = vid_queue2.static_pad("sink").unwrap();

    tee_convert_pad.link(&vid_queue2_pad).unwrap();


    


    How can I use tee in rust properly to have playable pipeline with two branches ?

    


    Update : I read some posts about increasing queue size, so I tried for this and then all queues :

    


        let vid_queue1 = gst::ElementFactory::make("queue")
        .name("queue1")
        .property("max-size-buffers", 5000 as u32)
        .property("max-size-bytes", 1048576000 as u32)
        .property("max-size-time", 60000000000 as u64)
        .build()
        .expect("queue1");


    


    but it didn't help so I tried set zero latency :

    


        let x264 = gst::ElementFactory::make("x264enc")
        .name("x264")
        .property_from_str("speed-preset", "ultrafast")
        .property_from_str("pass", "qual")
        .property_from_str("tune", "zerolatency")
        .property("quantizer", 0 as u32)
        .property("threads", 8 as u32)
        .build()
        .expect("!x264");


    


    and it works now. But comparable gst-launch-1.0 settings didn't had such option - only queues sizes increased.

    


    Is there any other option than setting zerolatency ?