Recherche avancée

Médias (1)

Mot : - Tags -/musée

Autres articles (62)

  • Les vidéos

    21 avril 2011, par

    Comme les documents de type "audio", Mediaspip affiche dans la mesure du possible les vidéos grâce à la balise html5 .
    Un des inconvénients de cette balise est qu’elle n’est pas reconnue correctement par certains navigateurs (Internet Explorer pour ne pas le nommer) et que chaque navigateur ne gère en natif que certains formats de vidéos.
    Son avantage principal quant à lui est de bénéficier de la prise en charge native de vidéos dans les navigateur et donc de se passer de l’utilisation de Flash et (...)

  • (Dés)Activation de fonctionnalités (plugins)

    18 février 2011, par

    Pour gérer l’ajout et la suppression de fonctionnalités supplémentaires (ou plugins), MediaSPIP utilise à partir de la version 0.2 SVP.
    SVP permet l’activation facile de plugins depuis l’espace de configuration de MediaSPIP.
    Pour y accéder, il suffit de se rendre dans l’espace de configuration puis de se rendre sur la page "Gestion des plugins".
    MediaSPIP est fourni par défaut avec l’ensemble des plugins dits "compatibles", ils ont été testés et intégrés afin de fonctionner parfaitement avec chaque (...)

  • Activation de l’inscription des visiteurs

    12 avril 2011, par

    Il est également possible d’activer l’inscription des visiteurs ce qui permettra à tout un chacun d’ouvrir soit même un compte sur le canal en question dans le cadre de projets ouverts par exemple.
    Pour ce faire, il suffit d’aller dans l’espace de configuration du site en choisissant le sous menus "Gestion des utilisateurs". Le premier formulaire visible correspond à cette fonctionnalité.
    Par défaut, MediaSPIP a créé lors de son initialisation un élément de menu dans le menu du haut de la page menant (...)

Sur d’autres sites (10137)

  • Video streamign with FFMpeg and Nest.js+Next.js

    17 septembre 2024, par Aizen

    Here 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 = [];&#xA;        &#xA;        await this.createDirectories(tempDir);        &#xA;        outputFiles.push(await this.convertVideo(inputFile, &#x27;1280x720&#x27;, &#x27;720p.mp4&#x27;));&#xA;        outputFiles.push(await this.convertVideo(inputFile, &#x27;854x480&#x27;, &#x27;480p.mp4&#x27;));&#xA;        console.log(&#x27;OUTUPT FILES SERVICE: &#x27;,outputFiles);&#xA;        &#xA;        return outputFiles;&#xA;&#xA;    }catch(err){&#xA;        console.error(&#x27;VideoFormatterService Error: &#x27;,err);&#xA;        &#xA;    }&#xA;}&#xA;&#xA;private convertVideo(inputPath:string,resolution:string,outputFileName:string):Promise<string>{&#xA;    const temp = `C:/Users/arMori/Desktop/RedditClone/reddit_back/src/video/temp`;&#xA;    return new Promise(async(resolve,reject)=>{&#xA;        const height = resolution.split(&#x27;x&#x27;)[1];&#xA;        console.log(&#x27;HIEGHT: &#x27;,height);&#xA;        &#xA;        const outputDir = `C:/Users/arMori/Desktop/RedditClone/reddit_back/src/video/temp/${height}p`;&#xA;        const outputPath = join(outputDir, outputFileName);&#xA;        const isExists = await fs.access(outputPath).then(() => true).catch(() => false);&#xA;        if(isExists){ &#xA;            console.log(`File already exists: ${outputPath}`);&#xA;            return resolve(outputPath)&#xA;        };&#xA;        ffmpeg(inputPath)&#xA;        .size(`${resolution}`)&#xA;        .videoCodec(&#x27;libx264&#x27;) // Кодек H.264&#xA;        .audioCodec(&#x27;aac&#x27;) &#xA;        .output(outputPath)&#xA;        .on(&#x27;end&#x27;,()=>resolve(outputPath))&#xA;        .on(&#x27;error&#x27;,(err)=>reject(err))&#xA;        .run()&#xA;            &#xA;    })&#xA;}&#xA;&#xA;private async createDirectories(temp:string){&#xA;    try{&#xA;        const dir720p = `${temp}/720p`;&#xA;        const dir480p = `${temp}/480p`;&#xA;        const dir720pExists = await fs.access(dir720p).then(() => true).catch(() => false);&#xA;        const dir480pExists = await fs.access(dir480p).then(() => true).catch(() => false);&#xA;        if(dir720pExists &amp;&amp; dir480pExists){&#xA;            console.log(&#x27;FILES ALIVE&#x27;);&#xA;            return;&#xA;        }&#xA;        if (!dir720pExists) {&#xA;            await fs.mkdir(dir720p, { recursive: true });&#xA;            console.log(&#x27;Папка 720p создана&#x27;);&#xA;        }&#xA;        &#xA;        if (!dir480pExists) {&#xA;            await fs.mkdir(dir480p, { recursive: true });&#xA;            console.log(&#x27;Папка 480p создана&#x27;);&#xA;        }&#xA;    } catch (err) {&#xA;        console.error(&#x27;Ошибка при создании директорий:&#x27;, err);&#xA;    }&#xA;}&#xA;</string>

    &#xA;

    Continue frontentd code :

    &#xA;

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

    &#xA;

    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 :

    &#xA;

    @Public()&#xA;    @Get(&#x27;/getVideo&#x27;)&#xA;    async getVideo(@Query(&#x27;path&#x27;) videoPath:string,@Req() req:Request,@Res() res:Response){&#xA;        try {&#xA;            console.log(&#x27;PATH ARGUMENT: &#x27;,videoPath);&#xA;            console.log(&#x27;VIDEOPATH IN SERVICE: &#x27;,videoPath);&#xA;        const videoSize = (await fs.stat(videoPath)).size;&#xA;        const CHUNK_SIZE = 10 ** 6;&#xA;        const range = req.headers[&#x27;range&#x27;] as string | undefined;&#xA;        if (!range) {&#xA;            return new ForbiddenException(&#x27;Range не найденно&#x27;);&#xA;        }&#xA;        const start = Number(range.replace(/\D/g,""));&#xA;        const end = Math.min(start &#x2B; CHUNK_SIZE,videoSize - 1);&#xA;&#xA;        const contentLength = end - start &#x2B; 1;&#xA;        const videoStream = fsSync.createReadStream(videoPath, { start, end });&#xA;        const headers = {&#xA;            &#x27;Content-Range&#x27;:`bytes ${start}-${end}/${videoSize}`,&#xA;            &#x27;Accept-Ranges&#x27;:&#x27;bytes&#x27;,&#xA;            &#x27;Content-Length&#x27;:contentLength,&#xA;            &#x27;Content-Type&#x27;:&#x27;video/mp4&#x27;&#xA;        }&#xA;        &#xA;        res.writeHead(206,headers);&#xA;&#xA;        // Передаем поток в ответ&#xA;        videoStream.pipe(res);&#xA;        &#xA;&#xA;        // Если возникнет ошибка при стриминге, логируем ошибку&#xA;        videoStream.on(&#x27;error&#x27;, (error) => {&#xA;            console.error(&#x27;Ошибка при чтении видео:&#x27;, error);&#xA;            res.status(500).send(&#x27;Ошибка при чтении видео&#x27;);&#xA;        });&#xA;        } catch (error) {&#xA;            console.error(&#x27;Ошибка при обработке запросов:&#x27;, error);&#xA;            return res.status(400).json({ message: &#x27;Ошибка при обработке getVideo запросов&#x27; });&#xA;        }&#xA;    }&#xA;

    &#xA;

    Send to the frontend

    &#xA;

    res.writeHead(206,headers);&#xA;

    &#xA;

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

    &#xA;

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

    &#xA;

    And assign src to the video :

    &#xA;

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

    &#xA;

    But the problem is :

    &#xA;

    &#xA;

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

    &#xA;

    &#xA;

    And I don't know why...

    &#xA;

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

    &#xA;

  • ffmpeg Command in Docker with Rust Tokio Closes Warp Server Connection (curl 52 Error)

    3 juin 2024, par user762345

    I’m encountering an issue where executing an ffmpeg concatenation command through Rust’s Tokio process in a Docker container causes subsequent HTTP requests to fail. The error occurs exclusively after running the ffmpeg command and making immediate requests, resulting in a “curl 52 empty response from server” error with the connection being closed. Notably, this issue does not occur when running the same setup outside of Docker. Additionally, if no HTTP requests are made after the ffmpeg command, the curl 52 error does not occur.

    &#xA;

    Here is the verbose curl output of my minimum reproducible example (see below).

    &#xA;

    curl -v "http://localhost:3030"&#xA;*   Trying 127.0.0.1:3030...&#xA;* Connected to localhost (127.0.0.1) port 3030 (#0)&#xA;> GET / HTTP/1.1&#xA;> Host: localhost:3030&#xA;> User-Agent: curl/8.1.2&#xA;> Accept: */*&#xA;> &#xA;* Empty reply from server&#xA;* Closing connection 0&#xA;curl: (52) Empty reply from server&#xA;

    &#xA;

    Here are Docker logs from my minimum reproducible example (see below). The wav files are concatenated successfully, then the container appears to rebuild.

    &#xA;

    [2024-06-03T05:26:58Z INFO  minimal_docker_webserver_post_error] Starting server on 0.0.0.0:3030&#xA;[2024-06-03T05:26:58Z INFO  warp::server] Server::run; addr=0.0.0.0:3030&#xA;[2024-06-03T05:26:58Z INFO  warp::server] listening on http://0.0.0.0:3030&#xA;[2024-06-03T05:27:07Z INFO  minimal_docker_webserver_post_error] WAV files concatenated successfully&#xA;[Running &#x27;cargo run&#x27;]&#xA;    Finished `dev` profile [unoptimized &#x2B; debuginfo] target(s) in 0.06s&#xA;     Running `target/debug/minimal_docker_webserver_post_error`&#xA;[2024-06-03T05:27:08Z INFO  minimal_docker_webserver_post_error] Starting server on 0.0.0.0:3030&#xA;[2024-06-03T05:27:08Z INFO  warp::server] Server::run; addr=0.0.0.0:3030&#xA;[2024-06-03T05:27:08Z INFO  warp::server] listening on http://0.0.0.0:3030&#xA;

    &#xA;

    What I have tried :&#xA;I tried using different web frameworks (Warp, Actix-web) and request crates (reqwest, ureq). I also tried running the setup outside of Docker, which worked as expected without any issues. Additionally, I tried running the setup in Docker without making any HTTP requests after the ffmpeg command, and the connection closed successfully without errors. I also tried posting to httpbin with a minimal request, but the issue persisted.

    &#xA;

    Minimum reproducible example :

    &#xA;

    main.rs

    &#xA;

    use warp::Filter;&#xA;use reqwest::Client;&#xA;use std::convert::Infallible;&#xA;use log::{info, error};&#xA;use env_logger;&#xA;use tokio::process::Command;&#xA;&#xA;#[tokio::main]&#xA;async fn main() {&#xA;    std::env::set_var("RUST_LOG", "debug");&#xA;    env_logger::init();&#xA;&#xA;    let route = warp::path::end()&#xA;        .and_then(handle_request);&#xA;&#xA;    info!("Starting server on 0.0.0.0:3030");&#xA;    warp::serve(route)&#xA;        .run(([0, 0, 0, 0], 3030))&#xA;        .await;&#xA;}&#xA;&#xA;async fn handle_request() -> Result<impl infallible="infallible"> {&#xA;    let client = Client::new();&#xA;&#xA;    let output = Command::new("ffmpeg")&#xA;        .args(&amp;[&#xA;            "y",&#xA;            "-i", "concat:/usr/src/minimal_docker_webserver_post_error/file1.wav|/usr/src/minimal_docker_webserver_post_error/file2.wav",&#xA;            "-c", "copy",&#xA;            "/usr/src/minimal_docker_webserver_post_error/combined.wav"&#xA;        ])&#xA;        .output()&#xA;        .await;&#xA;&#xA;    match output {&#xA;        Ok(output) => {&#xA;            if output.status.success() {&#xA;                info!("WAV files concatenated successfully");&#xA;            } else {&#xA;                error!("Failed to concatenate WAV files: {:?}", output);&#xA;                return Ok(warp::reply::with_status("Failed to concatenate WAV files", warp::http::StatusCode::INTERNAL_SERVER_ERROR));&#xA;            }&#xA;        },&#xA;        Err(e) => {&#xA;            error!("Failed to execute ffmpeg: {:?}", e);&#xA;            return Ok(warp::reply::with_status("Failed to execute ffmpeg", warp::http::StatusCode::INTERNAL_SERVER_ERROR));&#xA;        }&#xA;    }&#xA;&#xA;    // ISSUE: Connection closes with curl: (52) Empty reply from server&#xA;    match client.get("https://httpbin.org/get").send().await {&#xA;        Ok(response) => info!("GET request successful: {:?}", response),&#xA;        Err(e) => error!("GET request failed: {:?}", e),&#xA;    }&#xA;&#xA;    match client.post("https://httpbin.org/post")&#xA;        .body("field1=value1&amp;field2=value2")&#xA;        .send().await {&#xA;        Ok(response) => info!("POST request successful: {:?}", response),&#xA;        Err(e) => error!("POST request failed: {:?}", e),&#xA;    }&#xA;&#xA;    Ok(warp::reply::with_status("Request handled", warp::http::StatusCode::OK))&#xA;}&#xA;</impl>

    &#xA;

    FFMPEG command to generate the two wav files for concatenation

    &#xA;

    ffmpeg -f lavfi -i "sine=frequency=1000:duration=5" file1.wav &amp;&amp; ffmpeg -f lavfi -i "sine=frequency=500:duration=5" file2.wav&#xA;

    &#xA;

    Dockerfile

    &#xA;

    # Use the official Rust image as the base image&#xA;FROM rust:latest&#xA;&#xA;# Install cargo-watch&#xA;RUN cargo install cargo-watch&#xA;&#xA;# Install ffmpeg&#xA;RUN apt-get update &amp;&amp; apt-get install -y ffmpeg&#xA;&#xA;# Set the working directory inside the container&#xA;WORKDIR /usr/src/minimal_docker_webserver_post_error&#xA;&#xA;# Copy the Cargo.toml and Cargo.lock files&#xA;COPY Cargo.toml Cargo.lock ./&#xA;&#xA;# Copy the source code&#xA;COPY src ./src&#xA;&#xA;# Copy wav files&#xA;COPY file1.wav /usr/src/minimal_docker_webserver_post_error/file1.wav&#xA;COPY file2.wav /usr/src/minimal_docker_webserver_post_error/file2.wav&#xA;&#xA;# Install dependencies&#xA;RUN cargo build --release&#xA;&#xA;# Expose the port that the application will run on&#xA;EXPOSE 3030&#xA;&#xA;# Set the entry point to use cargo-watch&#xA;CMD ["cargo", "watch", "-x", "run"]&#xA;

    &#xA;

    Cargo.toml

    &#xA;

    [package]&#xA;name = "minimal_docker_webserver_post_error"&#xA;version = "0.1.0"&#xA;edition = "2021"&#xA;&#xA;# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html&#xA;&#xA;[dependencies]&#xA;warp = "0.3"&#xA;reqwest = { version = "0.12.4", features = ["json"] }&#xA;tokio = { version = "1", features = ["full"] }&#xA;log = "0.4"&#xA;env_logger = "0.11.3"&#xA;

    &#xA;

    Making the request to the warp server

    &#xA;

    curl -v "http://localhost:3030"&#xA;

    &#xA;

  • webrtc to rtmp send video from camera to rtmp link

    14 avril 2024, par Leo-Mahendra

    i cant send the video from webrtc which is converted to bufferd data for every 10seconds and send to server.js where it takes it via websockets and convert it to flv format using ffmpeg.

    &#xA;

    i am trying to send it to rtmp server named restreamer for start, here i tried to convert the buffer data and send it to rtmp link using ffmpeg commands, where i initially started to suceesfully save the file from webrtc to mp4 format for a duration of 2-3 minute.

    &#xA;

    after i tried to use webrtc to send video data for every 10 seconds and in server i tried to send it to rtmp but i cant send it, but i can see the connection of rtmp url and server is been taken place but i cant see the video i can see the logs in rtmp server as

    &#xA;

    2024-04-14 12:35:45 ts=2024-04-14T07:05:45Z level=INFO component="RTMP" msg="no streams available" action="INVALID" address=":1935" client="172.17.0.1:37700" path="/3d30c5a9-2059-4843-8957-da963c7bc19b.stream" who="PUBLISH"&#xA;2024-04-14 12:35:45 ts=2024-04-14T07:05:45Z level=INFO component="RTMP" msg="no streams available" action="INVALID" address=":1935" client="172.17.0.1:37716" path="/3d30c5a9-2059-4843-8957-da963c7bc19b.stream" who="PUBLISH"&#xA;2024-04-14 12:35:45 ts=2024-04-14T07:05:45Z level=INFO component="RTMP" msg="no streams available" action="INVALID" address=":1935" client="172.17.0.1:37728" path="/3d30c5a9-2059-4843-8957-da963c7bc19b.stream" who="PUBLISH"   &#xA;

    &#xA;

    my frontend code

    &#xA;

         const handleSendVideo = async () => {&#xA;        console.log("start");&#xA;    &#xA;        if (!ws) {&#xA;            console.error(&#x27;WebSocket connection not established.&#x27;);&#xA;            return;&#xA;        }&#xA;    &#xA;        try {&#xA;            const videoStream = await navigator.mediaDevices.getUserMedia({ video: true });&#xA;            const mediaRecorder = new MediaRecorder(videoStream);&#xA;    &#xA;            const requiredFrameSize = 460800;&#xA;            const frameDuration = 10 * 1000; // 10 seconds in milliseconds&#xA;    &#xA;            mediaRecorder.ondataavailable = async (event) => {&#xA;                if (ws.readyState !== WebSocket.OPEN) {&#xA;                    console.error(&#x27;WebSocket connection is not open.&#x27;);&#xA;                    return;&#xA;                }&#xA;    &#xA;                if (event.data.size > 0) {&#xA;                    const arrayBuffer = await event.data.arrayBuffer();&#xA;                    const uint8Array = new Uint8Array(arrayBuffer);&#xA;    &#xA;                    const width = videoStream.getVideoTracks()[0].getSettings().width;&#xA;                    const height = videoStream.getVideoTracks()[0].getSettings().height;&#xA;    &#xA;                    const numFrames = Math.ceil(uint8Array.length / requiredFrameSize);&#xA;    &#xA;                    for (let i = 0; i &lt; numFrames; i&#x2B;&#x2B;) {&#xA;                        const start = i * requiredFrameSize;&#xA;                        const end = Math.min((i &#x2B; 1) * requiredFrameSize, uint8Array.length);&#xA;                        let frameData = uint8Array.subarray(start, end);&#xA;    &#xA;                        // Pad or trim the frameData to match the required size&#xA;                        if (frameData.length &lt; requiredFrameSize) {&#xA;                            // Pad with zeros to reach the required size&#xA;                            const paddedData = new Uint8Array(requiredFrameSize);&#xA;                            paddedData.set(frameData, 0);&#xA;                            frameData = paddedData;&#xA;                        } else if (frameData.length > requiredFrameSize) {&#xA;                            // Trim to match the required size&#xA;                            frameData = frameData.subarray(0, requiredFrameSize);&#xA;                        }&#xA;    &#xA;                        const dataToSend = {&#xA;                            buffer: Array.from(frameData), // Convert Uint8Array to array of numbers&#xA;                            width: width,&#xA;                            height: height,&#xA;                            pixelFormat: &#x27;yuv420p&#x27;,&#xA;                            mode: &#x27;SendRtmp&#x27;&#xA;                        };&#xA;    &#xA;                        console.log("Sending frame:", i);&#xA;                        ws.send(JSON.stringify(dataToSend));&#xA;                    }&#xA;                }&#xA;            };&#xA;    &#xA;            // Start recording and send data every 10 seconds&#xA;            mediaRecorder.start(frameDuration);&#xA;    &#xA;            console.log("MediaRecorder started.");&#xA;        } catch (error) {&#xA;            console.error(&#x27;Error accessing media devices or starting recorder:&#x27;, error);&#xA;        }&#xA;      };&#xA;

    &#xA;

    and my backend

    &#xA;

        wss.on(&#x27;connection&#x27;, (ws) => {&#xA;    console.log(&#x27;WebSocket connection established.&#x27;);&#xA;&#xA;    ws.on(&#x27;message&#x27;, async (data) => {&#xA;        try {&#xA;            const parsedData = JSON.parse(data);&#xA;&#xA;            if (parsedData.mode === &#x27;SendRtmp&#x27; &amp;&amp; Array.isArray(parsedData.buffer)) {&#xA;                const { buffer, pixelFormat, width, height } = parsedData;&#xA;                const bufferArray = Buffer.from(buffer);&#xA;&#xA;                await sendRtmpVideo(bufferArray, pixelFormat, width, height);&#xA;            } else {&#xA;                console.log(&#x27;Received unknown or invalid mode or buffer data&#x27;);&#xA;            }&#xA;        } catch (error) {&#xA;            console.error(&#x27;Error parsing WebSocket message:&#x27;, error);&#xA;        }&#xA;    });&#xA;&#xA;    ws.on(&#x27;close&#x27;, () => {&#xA;        console.log(&#x27;WebSocket connection closed.&#x27;);&#xA;    });&#xA;    });&#xA;    const sendRtmpVideo = async (frameBuffer, pixelFormat, width, height) => {&#xA;    console.log("ffmpeg data",frameBuffer)&#xA;    try {&#xA;        const ratio = `${width}x${height}`;&#xA;        const ffmpegCommand = [&#xA;            &#x27;-re&#x27;,&#xA;            &#x27;-f&#x27;, &#x27;rawvideo&#x27;,&#xA;            &#x27;-pix_fmt&#x27;, pixelFormat,&#xA;            &#x27;-s&#x27;, ratio,&#xA;            &#x27;-i&#x27;, &#x27;pipe:0&#x27;,&#xA;            &#x27;-c:v&#x27;, &#x27;libx264&#x27;,&#xA;            &#x27;-preset&#x27;, &#x27;fast&#x27;, // Specify the preset for libx264&#xA;            &#x27;-b:v&#x27;, &#x27;3000k&#x27;,    // Specify the video bitrate&#xA;            &#x27;-loglevel&#x27;, &#x27;debug&#x27;,&#xA;            &#x27;-f&#x27;, &#x27;flv&#x27;,&#xA;            // &#x27;-flvflags&#x27;, &#x27;no_duration_filesize&#x27;, &#xA;            RTMPLINK&#xA;        ];&#xA;&#xA;&#xA;        const ffmpeg = spawn(&#x27;ffmpeg&#x27;, ffmpegCommand);&#xA;&#xA;        ffmpeg.on(&#x27;exit&#x27;, (code, signal) => {&#xA;            if (code === 0) {&#xA;                console.log(&#x27;FFmpeg process exited successfully.&#x27;);&#xA;            } else {&#xA;                console.error(`FFmpeg process exited with code ${code} and signal ${signal}`);&#xA;            }&#xA;        });&#xA;&#xA;        ffmpeg.on(&#x27;error&#x27;, (error) => {&#xA;            console.error(&#x27;FFmpeg spawn error:&#x27;, error);&#xA;        });&#xA;&#xA;        ffmpeg.stderr.on(&#x27;data&#x27;, (data) => {&#xA;            console.error(`FFmpeg stderr: ${data}`);&#xA;        });&#xA;&#xA;        ffmpeg.stdin.write(frameBuffer, (err) => {&#xA;            if (err) {&#xA;                console.error(&#x27;Error writing to FFmpeg stdin:&#x27;, err);&#xA;            } else {&#xA;                console.log(&#x27;Data written to FFmpeg stdin successfully.&#x27;);&#xA;            }&#xA;            ffmpeg.stdin.end(); // Close stdin after writing the buffer&#xA;        });&#xA;        } catch (error) {&#xA;        console.error(&#x27;Error in sendRtmpVideo:&#x27;, error);&#xA;        }&#xA;    };&#xA;&#xA;

    &#xA;