Recherche avancée

Médias (91)

Autres articles (31)

  • Librairies et binaires spécifiques au traitement vidéo et sonore

    31 janvier 2010, par

    Les logiciels et librairies suivantes sont utilisées par SPIPmotion d’une manière ou d’une autre.
    Binaires obligatoires FFMpeg : encodeur principal, permet de transcoder presque tous les types de fichiers vidéo et sonores dans les formats lisibles sur Internet. CF ce tutoriel pour son installation ; Oggz-tools : outils d’inspection de fichiers ogg ; Mediainfo : récupération d’informations depuis la plupart des formats vidéos et sonores ;
    Binaires complémentaires et facultatifs flvtool2 : (...)

  • Support audio et vidéo HTML5

    10 avril 2011

    MediaSPIP utilise les balises HTML5 video et audio pour la lecture de documents multimedia en profitant des dernières innovations du W3C supportées par les navigateurs modernes.
    Pour les navigateurs plus anciens, le lecteur flash Flowplayer est utilisé.
    Le lecteur HTML5 utilisé a été spécifiquement créé pour MediaSPIP : il est complètement modifiable graphiquement pour correspondre à un thème choisi.
    Ces technologies permettent de distribuer vidéo et son à la fois sur des ordinateurs conventionnels (...)

  • De l’upload à la vidéo finale [version standalone]

    31 janvier 2010, par

    Le chemin d’un document audio ou vidéo dans SPIPMotion est divisé en trois étapes distinctes.
    Upload et récupération d’informations de la vidéo source
    Dans un premier temps, il est nécessaire de créer un article SPIP et de lui joindre le document vidéo "source".
    Au moment où ce document est joint à l’article, deux actions supplémentaires au comportement normal sont exécutées : La récupération des informations techniques des flux audio et video du fichier ; La génération d’une vignette : extraction d’une (...)

Sur d’autres sites (5175)

  • Error initializing FFmpegKit : "TypeError : Cannot read property 'getLogLevel' of null" in React Native

    9 janvier, par Md Monirozzaman khan

    I'm developing a React Native application where I need to process videos using the ffmpeg-kit-react-native library. However, I'm encountering an issue during the initialization of FFmpegKitConfig. The error message is :

    


    ERROR  Error initializing FFmpegKit: [TypeError: Cannot read property 'getLogLevel' of null]


    


    Here is my App.js code

    


    

    

    import React, { useState, useEffect } from &#x27;react&#x27;;&#xA;import { StyleSheet, Text, View, TouchableOpacity, Alert, Dimensions, ScrollView, LayoutAnimation, UIManager, Platform } from &#x27;react-native&#x27;;&#xA;import * as ImagePicker from &#x27;expo-image-picker&#x27;;&#xA;import * as FileSystem from &#x27;expo-file-system&#x27;;&#xA;import { Video } from &#x27;expo-av&#x27;;&#xA;import { MaterialIcons } from &#x27;@expo/vector-icons&#x27;;&#xA;import { FFmpegKit, FFmpegKitConfig, ReturnCode } from &#x27;ffmpeg-kit-react-native&#x27;;&#xA;&#xA;const windowWidth = Dimensions.get(&#x27;window&#x27;).width;&#xA;&#xA;if (Platform.OS === &#x27;android&#x27;) {&#xA;  UIManager.setLayoutAnimationEnabledExperimental &amp;&amp; UIManager.setLayoutAnimationEnabledExperimental(true);&#xA;}&#xA;&#xA;export default function App() {&#xA;  const [videoFiles, setVideoFiles] = useState([]);&#xA;  const [isGridView, setIsGridView] = useState(false);&#xA;  const [isConverting, setIsConverting] = useState(false);&#xA;&#xA;  useEffect(() => {&#xA;    FFmpegKitConfig.init()&#xA;      .then(() => {&#xA;        console.log(&#x27;FFmpegKit initialized&#x27;);&#xA;      })&#xA;      .catch((error) => {&#xA;        console.error(&#x27;Error initializing FFmpegKit:&#x27;, error);&#xA;      });&#xA;  }, []);&#xA;&#xA;  const pickVideo = async () => {&#xA;    const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();&#xA;    if (status !== &#x27;granted&#x27;) {&#xA;      alert(&#x27;Sorry, we need media library permissions to make this work!&#x27;);&#xA;      return;&#xA;    }&#xA;&#xA;    let result = await ImagePicker.launchImageLibraryAsync({&#xA;      mediaTypes: ImagePicker.MediaTypeOptions.Videos,&#xA;      allowsMultipleSelection: true,&#xA;    });&#xA;&#xA;    if (!result.canceled &amp;&amp; result.assets.length > 0) {&#xA;      const newFiles = result.assets.filter(&#xA;        (newFile) => !videoFiles.some((existingFile) => existingFile.uri === newFile.uri)&#xA;      );&#xA;&#xA;      if (newFiles.length &lt; result.assets.length) {&#xA;        Alert.alert(&#x27;Duplicate Files&#x27;, &#x27;Some files were already added.&#x27;);&#xA;      }&#xA;&#xA;      LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);&#xA;      setVideoFiles([...videoFiles, ...newFiles]);&#xA;    }&#xA;  };&#xA;&#xA;  const convertVideos = async () => {&#xA;    setIsConverting(true);&#xA;    const outputDir = `${FileSystem.documentDirectory}Output`;&#xA;&#xA;    const dirInfo = await FileSystem.getInfoAsync(outputDir);&#xA;    if (!dirInfo.exists) {&#xA;      await FileSystem.makeDirectoryAsync(outputDir, { intermediates: true });&#xA;    }&#xA;&#xA;    for (const video of videoFiles) {&#xA;      const { uri } = video;&#xA;      const filename = uri.split(&#x27;/&#x27;).pop();&#xA;      const outputFilePath = `${outputDir}/${filename.split(&#x27;.&#x27;).slice(0, -1).join(&#x27;.&#x27;)}_modified.mp4`;&#xA;&#xA;      const ffmpegCommand = `-y -i "${uri}" -af "atempo=1.02, bass=g=4:f=80:w=3, treble=g=4:f=3200:w=3, firequalizer=gain_entry=&#x27;entry(0,0);entry(62,2);entry(125,1.5);entry(250,1);entry(500,1);entry(1000,1);entry(2000,1.5);entry(4000,2.5);entry(8000,3);entry(16000,4)&#x27;, compand=attacks=0.05:decays=0.25:points=-80/-80-50/-15-30/-10-10/-2:soft-knee=4:gain=2, deesser, highpass=f=35, lowpass=f=17000, loudnorm=I=-16:LRA=11:TP=-1.5, volume=3.9dB" -c:v copy -c:a aac -b:a 224k -ar 48000 -threads 0 "${outputFilePath}"`;&#xA;&#xA;      try {&#xA;        const session = await FFmpegKit.execute(ffmpegCommand);&#xA;        const returnCode = await session.getReturnCode();&#xA;&#xA;        if (ReturnCode.isSuccess(returnCode)) {&#xA;          console.log(`Video converted: ${outputFilePath}`);&#xA;        } else if (ReturnCode.isCancel(returnCode)) {&#xA;          console.log(&#x27;Conversion cancelled&#x27;);&#xA;        } else {&#xA;          console.error(`FFmpeg process failed: ${session.getFailStackTrace()}`);&#xA;        }&#xA;      } catch (error) {&#xA;        console.error(`Error converting video: ${error.message}`);&#xA;      }&#xA;    }&#xA;&#xA;    setIsConverting(false);&#xA;    Alert.alert(&#x27;Conversion Complete&#x27;, &#x27;All videos have been converted.&#x27;);&#xA;  };&#xA;&#xA;  const deleteVideo = (uri) => {&#xA;    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);&#xA;    setVideoFiles(videoFiles.filter((video) => video.uri !== uri));&#xA;  };&#xA;&#xA;  const clearAllVideos = () => {&#xA;    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);&#xA;    setVideoFiles([]);&#xA;  };&#xA;&#xA;  const toggleLayout = () => {&#xA;    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);&#xA;    setIsGridView(!isGridView);&#xA;  };&#xA;&#xA;  return (&#xA;    <view style="{styles.container}">&#xA;      <text style="{styles.header}">Video Converter App</text>&#xA;      <touchableopacity style="{styles.addButton}">&#xA;        <text style="{styles.addButtonText}">Select or Browse Videos</text>&#xA;      </touchableopacity>&#xA;      <view style="{styles.headerContainer}">&#xA;        <text style="{styles.videoCount}">Total Videos: {videoFiles.length}</text>&#xA;        {videoFiles.length > 0 &amp;&amp; (&#xA;          &lt;>&#xA;            <touchableopacity style="{styles.clearButtonContainer}">&#xA;              <materialicons size="{24}" color="red" style="{styles.clearIcon}"></materialicons>&#xA;              <text style="{styles.clearAllText}">Clear All</text>&#xA;            </touchableopacity>&#xA;            <touchableopacity style="{styles.toggleLayoutButton}">&#xA;              <materialicons size="{24}" color="#fff"></materialicons>&#xA;            </touchableopacity>&#xA;          >&#xA;        )}&#xA;      </view>&#xA;      {isGridView ? (&#xA;        <scrollview contentcontainerstyle="{styles.gridContainer}">&#xA;          {videoFiles.map((item, index) => (&#xA;            <view key="{index}" style="{styles.videoItemGrid}">&#xA;              &#xA;              <touchableopacity>> deleteVideo(item.uri)} style={styles.deleteButtonGrid}>&#xA;                <materialicons size="{24}" color="red"></materialicons>&#xA;              </touchableopacity>&#xA;            </view>&#xA;          ))}&#xA;        </scrollview>&#xA;      ) : (&#xA;        <view style="{styles.list}">&#xA;          {videoFiles.map((item, index) => (&#xA;            <view key="{index}" style="{styles.videoItem}">&#xA;              &#xA;              <text style="{styles.fileName}">{decodeURI(item.fileName || item.uri.split(&#x27;/&#x27;).pop() || &#x27;Unknown File&#x27;)}</text>&#xA;              <touchableopacity>> deleteVideo(item.uri)} style={styles.deleteButton}>&#xA;                <materialicons size="{24}" color="red"></materialicons>&#xA;              </touchableopacity>&#xA;            </view>&#xA;          ))}&#xA;        </view>&#xA;      )}&#xA;      {videoFiles.length > 0 &amp;&amp; (&#xA;        <touchableopacity style="{styles.convertButton}" disabled="{isConverting}">&#xA;          <text style="{styles.convertButtonText}">{isConverting ? &#x27;Converting...&#x27; : &#x27;Convert&#x27;}</text>&#xA;        </touchableopacity>&#xA;      )}&#xA;    </view>&#xA;  );&#xA;}&#xA;&#xA;const styles = StyleSheet.create({&#xA;  container: {&#xA;    flex: 1,&#xA;    backgroundColor: &#x27;#fff&#x27;,&#xA;    alignItems: &#x27;center&#x27;,&#xA;    padding: 10,&#xA;  },&#xA;  header: {&#xA;    fontSize: 24,&#xA;    fontWeight: &#x27;bold&#x27;,&#xA;    marginBottom: 5,&#xA;  },&#xA;  addButton: {&#xA;    backgroundColor: &#x27;#007BFF&#x27;,&#xA;    padding: 15,&#xA;    borderRadius: 10,&#xA;    alignItems: &#x27;center&#x27;,&#xA;    marginBottom: 5,&#xA;    width: &#x27;100%&#x27;,&#xA;    elevation: 2,&#xA;    shadowColor: &#x27;#000&#x27;,&#xA;    shadowOffset: { width: 0, height: 5 },&#xA;    shadowOpacity: 0.8,&#xA;    shadowRadius: 2,&#xA;  },&#xA;  addButtonText: {&#xA;    color: &#x27;#fff&#x27;,&#xA;    fontSize: 18,&#xA;    fontWeight: &#x27;bold&#x27;,&#xA;  },&#xA;  headerContainer: {&#xA;    flexDirection: &#x27;row&#x27;,&#xA;    alignItems: &#x27;center&#x27;,&#xA;    justifyContent: &#x27;space-between&#x27;,&#xA;    width: &#x27;100%&#x27;,&#xA;    marginBottom: 10,&#xA;  },&#xA;  videoCount: {&#xA;    fontSize: 18,&#xA;  },&#xA;  clearButtonContainer: {&#xA;    flexDirection: &#x27;row&#x27;,&#xA;    alignItems: &#x27;center&#x27;,&#xA;    marginRight: 10,&#xA;  },&#xA;  clearIcon: {&#xA;    marginRight: 5,&#xA;  },&#xA;  clearAllText: {&#xA;    fontSize: 16,&#xA;    color: &#x27;red&#x27;,&#xA;    textDecorationLine: &#x27;underline&#x27;,&#xA;  },&#xA;  toggleLayoutButton: {&#xA;    backgroundColor: &#x27;#007BFF&#x27;,&#xA;    padding: 1,&#xA;    borderRadius: 8,&#xA;    alignItems: &#x27;center&#x27;,&#xA;    justifyContent: &#x27;center&#x27;,&#xA;  },&#xA;  list: {&#xA;    flex: 1,&#xA;    width: &#x27;100%&#x27;,&#xA;  },&#xA;  videoItem: {&#xA;    padding: 5,&#xA;    borderBottomColor: &#x27;#ccc&#x27;,&#xA;    borderBottomWidth: 0.7,&#xA;    flexDirection: &#x27;row&#x27;,&#xA;    alignItems: &#x27;center&#x27;,&#xA;  },&#xA;  videoItemGrid: {&#xA;    flexDirection: &#x27;column&#x27;,&#xA;    alignItems: &#x27;center&#x27;,&#xA;    margin: 4,&#xA;    borderWidth: 1,&#xA;    borderColor: &#x27;#ccc&#x27;,&#xA;    borderRadius: 8,&#xA;    padding: 2,&#xA;    position: &#x27;relative&#x27;,&#xA;  },&#xA;  thumbnail: {&#xA;    width: 70,&#xA;    height: 70,&#xA;    marginRight: 10,&#xA;  },&#xA;  thumbnailGrid: {&#xA;    width: 80,&#xA;    height: 80,&#xA;    marginBottom: 0,&#xA;  },&#xA;  fileName: {&#xA;    fontSize: 16,&#xA;    marginLeft: 10,&#xA;    flex: 1,&#xA;  },&#xA;  deleteButton: {&#xA;    marginLeft: 60,&#xA;    width: 20,&#xA;    height: 20,&#xA;  },&#xA;  deleteButtonGrid: {&#xA;    position: &#x27;absolute&#x27;,&#xA;    bottom: 5,&#xA;    right: 5,&#xA;  },&#xA;  convertButton: {&#xA;    backgroundColor: &#x27;#007BFF&#x27;,&#xA;    padding: 15,&#xA;    borderRadius: 10,&#xA;    alignItems: &#x27;center&#x27;,&#xA;    marginTop: 20,&#xA;    width: &#x27;100%&#x27;,&#xA;  },&#xA;  convertButtonText: {&#xA;    color: &#x27;#fff&#x27;,&#xA;    fontSize: 18,&#xA;    fontWeight: &#x27;bold&#x27;,&#xA;  },&#xA;  gridContainer: {&#xA;    flexDirection: &#x27;row&#x27;,&#xA;    flexWrap: &#x27;wrap&#x27;,&#xA;    justifyContent: &#x27;flex-start&#x27;,&#xA;    paddingVertical: 5,&#xA;    paddingHorizontal: 5,&#xA;    width: &#x27;100%&#x27;,&#xA;  },&#xA;});

    &#xD;&#xA;

    &#xD;&#xA;

    &#xD;&#xA;&#xA;

    App.json

    &#xA;

    &#xD;&#xA;
    &#xD;&#xA;
    {&#xA;  "expo": {&#xA;    "name": "VidoeConvert",&#xA;    "slug": "VidoeConvert",&#xA;    "version": "1.0.0",&#xA;    "orientation": "portrait",&#xA;    "icon": "./assets/icon.png",&#xA;    "userInterfaceStyle": "light",&#xA;    "splash": {&#xA;      "image": "./assets/splash.png",&#xA;      "resizeMode": "contain",&#xA;      "backgroundColor": "#ffffff"&#xA;    },&#xA;    "ios": {&#xA;      "supportsTablet": true&#xA;    },&#xA;    "android": {&#xA;      "adaptiveIcon": {&#xA;        "foregroundImage": "./assets/adaptive-icon.png",&#xA;        "backgroundColor": "#ffffff"&#xA;      },&#xA;      "package": "com.anonymous.VidoeConvert"&#xA;    },&#xA;    "web": {&#xA;      "favicon": "./assets/favicon.png"&#xA;    },&#xA;    "plugins": [&#xA;      "@config-plugins/ffmpeg-kit-react-native",&#xA;      "expo-build-properties"&#xA;    ]&#xA;  }&#xA;}

    &#xD;&#xA;

    &#xD;&#xA;

    &#xD;&#xA;&#xA;

    Package.json

    &#xA;

    &#xD;&#xA;
    &#xD;&#xA;
    {&#xA;  "name": "vidoeconvert",&#xA;  "version": "1.0.0",&#xA;  "main": "expo/AppEntry.js",&#xA;  "scripts": {&#xA;    "start": "expo start",&#xA;    "android": "expo run:android",&#xA;    "ios": "expo run:ios",&#xA;    "web": "expo start --web"&#xA;  },&#xA;  "dependencies": {&#xA;    "@config-plugins/ffmpeg-kit-react-native": "^8.0.0",&#xA;    "@expo/metro-runtime": "~3.2.1",&#xA;    "expo": "~51.0.17",&#xA;    "expo-asset": "~10.0.10",&#xA;    "expo-av": "^14.0.6",&#xA;    "expo-document-picker": "~12.0.2",&#xA;    "expo-file-system": "~17.0.1",&#xA;    "expo-image-picker": "~15.0.7",&#xA;    "expo-media-library": "~16.0.4",&#xA;    "expo-status-bar": "~1.12.1",&#xA;    "ffmpeg-kit-react-native": "^6.0.2",&#xA;    "react": "18.2.0",&#xA;    "react-dom": "18.2.0",&#xA;    "react-native": "^0.74.3",&#xA;    "react-native-document-picker": "^9.3.0",&#xA;    "react-native-ffmpeg": "^0.5.2",&#xA;    "react-native-vector-icons": "^10.1.0",&#xA;    "react-native-web": "~0.19.10",&#xA;    "expo-build-properties": "~0.12.3"&#xA;  },&#xA;  "devDependencies": {&#xA;    "@babel/core": "^7.20.0"&#xA;  },&#xA;  "private": true&#xA;}

    &#xD;&#xA;

    &#xD;&#xA;

    &#xD;&#xA;&#xA;

    Has anyone encountered a similar issue or can point me in the right direction to resolve this error ? Any help would be greatly appreciated !

    &#xA;

    How to remove the error ?

    &#xA;

    any configruation required for this project ?

    &#xA;

  • How to fix here "EPIPE" in Node js Socket.io

    23 avril, par Mehdi008

    Receiving this error :

    &#xA;

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

    &#xA;

    // for this code: const { spawn } = require("child_process");&#xA;&#xA;module.exports = (socket, pool) => {&#xA;    &#xA;    let stream_req_token = "";&#xA;    let rtmps_array = [];&#xA;&#xA;    socket.on("stream_request_token",async(token)=>{&#xA;&#xA;        const stream_reqs = await pool`SELECT * FROM stream_request WHERE token=${token}`;&#xA;&#xA;&#xA;        if(stream_reqs.length === 0){&#xA;            &#xA;            socket.emit("token_validation_response",false);&#xA;            return;&#xA;        }&#xA;&#xA;        const stream_req = stream_reqs[0];&#xA;&#xA;        if(!stream_req.is_valid){&#xA;&#xA;            socket.emit("token_validation_response",false);&#xA;            return;&#xA;        }&#xA;&#xA;        socket.emit("token_validation_response",true);&#xA;&#xA;        stream_req_token = token;&#xA;&#xA;&#xA;    })&#xA;&#xA;    socket.on("rtmps_array",async(array)=>{&#xA;&#xA;        try{&#xA;&#xA;            const rtmps = JSON.parse(array);&#xA;&#xA;        const streams_requests = await pool`SELECT id FROM stream_request WHERE token=${stream_req_token}`;&#xA;        const stream_req_id = streams_requests[0].id;&#xA;&#xA;        rtmps_array = rtmps;&#xA;&#xA;        rtmps.map(async(rtmp)=>{&#xA;&#xA;            await pool`INSERT INTO stream (platform,url,url_key,stream_request_id) &#xA;            VALUES(${rtmp.platform},${rtmp.url},${rtmp.key},${stream_req_id})`;&#xA;        })&#xA;&#xA;        socket.emit("rtmps_array_response",true);&#xA;&#xA;        } catch(err){&#xA;&#xA;            console.log(err);&#xA;            socket.emit("rtmps_array_response",false);&#xA;&#xA;        }&#xA;&#xA;&#xA;    })&#xA;&#xA;    //Start Streaming&#xA;    let ffmpegProcess = null;&#xA;    let isStreaming = false; // Flag to track streaming state&#xA;&#xA;  socket.on("stream", (chunk) => {&#xA;    if (!ffmpegProcess) {&#xA;        console.log(&#x27;Initializing FFmpeg process...&#x27;);&#xA;&#xA;        // Spawn FFmpeg process&#xA;        const resolution = "1280x720"; // Change to "1920x1080" for 1080p&#xA;&#xA;        const ffmpegArgs = [&#xA;            "-i", "pipe:0", // Input from stdin&#xA;            "-c:v", "libx264", // Video codec&#xA;            "-preset", "veryfast", // Low latency encoding&#xA;            "-b:v", "4500k", // Target average bitrate (4.5 Mbps)&#xA;            "-minrate", "2500k", // Minimum bitrate&#xA;            "-maxrate", "6000k", // Maximum bitrate&#xA;            "-bufsize", "16000k", // Buffer size (twice the max bitrate)&#xA;            "-r", "30", // **FORCE 30 FPS**&#xA;            "-g", "60", // Keyframe interval (every 2 seconds)&#xA;            "-tune", "zerolatency", // Low latency tuning&#xA;            "-sc_threshold", "0", // Constant bitrate enforcement&#xA;            "-flags", "&#x2B;global_header",&#xA;          &#xA;            // **Resolution Fix**&#xA;            "-s", resolution, // **Set resolution to 720p or 1080p**&#xA;            "-aspect", "16:9", // **Maintain aspect ratio**&#xA;            &#xA;            // **Frame Rate Fix**&#xA;            "-vsync", "cfr", // **Forces Constant Frame Rate (CFR)**&#xA;            "-fps_mode", "cfr", // **Prevents FFmpeg from auto-adjusting FPS**&#xA;            &#xA;            // Audio settings&#xA;            "-c:a", "aac",&#xA;            "-b:a", "128k", // Audio bitrate&#xA;            "-ar", "44100", // Audio sample rate&#xA;            "-ac", "2", // Stereo audio&#xA;          &#xA;            "-f", "flv" // Output format&#xA;          ];&#xA;      &#xA;          // Map the streams to multiple RTMP destinations&#xA;          rtmps_array.forEach((rtmp) => {&#xA;            ffmpegArgs.push("-map", "0:v:0", "-map", "0:a:0", "-f", "flv", `${rtmp.url}/${rtmp.key}`);&#xA;          });&#xA;      &#xA;          // Spawn FFmpeg process&#xA;          ffmpegProcess = spawn("ffmpeg", ffmpegArgs);&#xA;&#xA;        ffmpegProcess.stderr.on(&#x27;data&#x27;, (data) => {&#xA;            console.log(`FFmpeg STDERR: ${data}`);&#xA;    });&#xA;&#xA;        ffmpegProcess.on(&#x27;close&#x27;, (code) => {&#xA;            console.log(`FFmpeg process closed with code ${code}`);&#xA;            ffmpegProcess = null; // Reset process&#xA;            isStreaming = false; // Reset streaming state&#xA;        });&#xA;&#xA;        ffmpegProcess.on(&#x27;error&#x27;, (err) => {&#xA;            console.error(`FFmpeg process error: ${err.message}`);&#xA;            ffmpegProcess = null; // Reset process&#xA;            isStreaming = false; // Reset streaming state&#xA;        });&#xA;&#xA;        console.log(&#x27;FFmpeg process started.&#x27;);&#xA;        isStreaming = true; // Set streaming state to true&#xA;    }&#xA;&#xA;    // Write chunk to FFmpeg process&#xA;    if (isStreaming &amp;&amp; ffmpegProcess &amp;&amp; ffmpegProcess.stdin &amp;&amp; !ffmpegProcess.stdin.destroyed) {&#xA;        try {&#xA;            ffmpegProcess.stdin.write(chunk); // Write chunk to stdin&#xA;            console.log(&#x27;Chunk written to FFmpeg.&#x27;);&#xA;        } catch (err) {&#xA;            console.error(&#x27;Error writing chunk to FFmpeg stdin:&#x27;, err.message);&#xA;        }&#xA;    } else {&#xA;        console.error(&#x27;FFmpeg process or stdin is not ready.&#x27;);&#xA;    }&#xA;});&#xA;&#xA;socket.on("stop-stream", async() => {&#xA;    console.log(&#x27;Stream Stopped.&#x27;);&#xA;&#xA;    if(stream_req_token.length !== 0){&#xA;&#xA;        await pool`UPDATE stream_request &#xA;               SET is_valid=false&#xA;               WHERE token=${stream_req_token}`&#xA;&#xA;        await pool`DELETE FROM current_streams WHERE id=${stream_req_token}`;       &#xA;    }&#xA;&#xA;    if (ffmpegProcess) {&#xA;        isStreaming = false; // Set streaming state to false&#xA;&#xA;        try {&#xA;            // Check if stdin is open before closing&#xA;            if (ffmpegProcess.stdin) {&#xA;                ffmpegProcess.stdin.end(); // End stdin safely&#xA;            }&#xA;&#xA;            // Wait for FFmpeg to close before setting to null&#xA;            ffmpegProcess.on("close", () => {&#xA;                console.log("FFmpeg process closed.");&#xA;                ffmpegProcess = null;&#xA;            });&#xA;&#xA;            // Kill FFmpeg process&#xA;            ffmpegProcess.kill("SIGTERM"); // Use SIGTERM for graceful exit&#xA;&#xA;        } catch (err) {&#xA;            console.error("Error while stopping FFmpeg:", err.message);&#xA;        }&#xA;    } else {&#xA;        console.log("No active FFmpeg process.");&#xA;    }&#xA;});&#xA;&#xA;&#xA;socket.on(&#x27;error&#x27;, (err) => {&#xA;  console.error(&#x27;Socket error:&#x27;, err);&#xA;});&#xA;&#xA;socket.on("disconnect", async() => {&#xA;    console.log(&#x27;Client Disconnected.&#x27;);&#xA;&#xA;    if(stream_req_token.length !== 0){&#xA;&#xA;        await pool`UPDATE stream_request &#xA;               SET is_valid=false&#xA;               WHERE token=${stream_req_token}`;&#xA;&#xA;        await pool`DELETE FROM current_streams WHERE id=${stream_req_token}`;       &#xA;&#xA;    }&#xA;    &#xA;    if (ffmpegProcess) {&#xA;        isStreaming = false; // Set streaming state to false&#xA;&#xA;        try {&#xA;            // Check if stdin is open before closing&#xA;            if (ffmpegProcess.stdin) {&#xA;                ffmpegProcess.stdin.end(); // End stdin safely&#xA;            }&#xA;&#xA;            // Wait for FFmpeg to close before setting to null&#xA;            ffmpegProcess.on("close", () => {&#xA;                console.log("FFmpeg process closed.");&#xA;                ffmpegProcess = null;&#xA;            });&#xA;&#xA;            // Kill FFmpeg process&#xA;            ffmpegProcess.kill("SIGTERM"); // Use SIGTERM for graceful exit&#xA;&#xA;&#xA;        } catch (err) {&#xA;            console.error("Error while stopping FFmpeg:", err.message);&#xA;        }&#xA;    } else {&#xA;        console.log("No active FFmpeg process.");&#xA;    }&#xA;});&#xA;&#xA;};&#xA;

    &#xA;

    &#xA;

  • What format/protocol does ffmpeg use for "raw" output ?

    18 avril 2017, par MSalters

    Given a commandline ffmpeg -f lavfi -i "sine=frequency=1000:duration=5" -ar 8000 -c:a FOO pipe:1, ffmpeg might complain it’s "unable to find a suitable output format". For some codecs, ffmpeg has a default container format, e.g. -c:a libmp3lame will produce MP3’s. For other codecs, you just repeat yourself (sort of) : -c:a pcm_alaw -f alaw

    But what if I want to stream the raw codec output, and there’s no matching -f ? Can I just take -f alaw and assume that it doesn’t do anything ? (G711 alaw is a simple codec which produces a byte stream, so -f alaw presumably just copies that byte stream)

    Obviously the other side of the pipe needs to know how the data stream needs to be interpreted, if there’s no container info. But assume that I already know the other side of the pipe is expecting an audio stream, sampled at 8 kHz, encoded with -c:a FOO.