Recherche avancée

Médias (0)

Mot : - Tags -/clipboard

Aucun média correspondant à vos critères n’est disponible sur le site.

Autres articles (71)

  • Amélioration de la version de base

    13 septembre 2013

    Jolie 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 (...)

  • Menus personnalisés

    14 novembre 2010, par

    MediaSPIP utilise le plugin Menus pour gérer plusieurs menus configurables pour la navigation.
    Cela permet de laisser aux administrateurs de canaux la possibilité de configurer finement ces menus.
    Menus créés à l’initialisation du site
    Par défaut trois menus sont créés automatiquement à l’initialisation du site : Le menu principal ; Identifiant : barrenav ; Ce menu s’insère en général en haut de la page après le bloc d’entête, son identifiant le rend compatible avec les squelettes basés sur Zpip ; (...)

  • Déploiements possibles

    31 janvier 2010, par

    Deux types de déploiements sont envisageable dépendant de deux aspects : La méthode d’installation envisagée (en standalone ou en ferme) ; Le nombre d’encodages journaliers et la fréquentation envisagés ;
    L’encodage de vidéos est un processus lourd consommant énormément de ressources système (CPU et RAM), il est nécessaire de prendre tout cela en considération. Ce système n’est donc possible que sur un ou plusieurs serveurs dédiés.
    Version mono serveur
    La version mono serveur consiste à n’utiliser qu’une (...)

Sur d’autres sites (12384)

  • 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;

  • Emscripten and Web Audio API

    29 avril 2015, par Multimedia Mike — HTML5

    Ha ! They said it couldn’t be done ! Well, to be fair, I said it couldn’t be done. Or maybe that I just didn’t have any plans to do it. But I did it– I used Emscripten to cross-compile a CPU-intensive C/C++ codebase (Game Music Emu) to JavaScript. Then I leveraged the Web Audio API to output audio and visualize the audio using an HTML5 canvas.

    Want to see it in action ? Here’s a demonstration. Perhaps I will be able to expand the reach of my Game Music site when I can drop the odd Native Client plugin. This JS-based player works great on Chrome, Firefox, and Safari across desktop operating systems.

    But this endeavor was not without its challenges.

    Programmatically Generating Audio
    First, I needed to figure out the proper method for procedurally generating audio and making it available to output. Generally, there are 2 approaches for audio output :

    1. Sit in a loop and generate audio, writing it out via a blocking audio call
    2. Implement a callback that the audio system can invoke in order to generate more audio when needed

    Option #1 is not a good idea for an event-driven language like JavaScript. So I hunted through the rather flexible Web Audio API for a method that allowed something like approach #2. Callbacks are everywhere, after all.

    I eventually found what I was looking for with the ScriptProcessorNode. It seems to be intended to apply post-processing effects to audio streams. A program registers a callback which is passed configurable chunks of audio for processing. I subverted this by simply overwriting the input buffers with the audio generated by the Emscripten-compiled library.

    The ScriptProcessorNode interface is fairly well documented and works across multiple browsers. However, it is already marked as deprecated :

    Note : As of the August 29 2014 Web Audio API spec publication, this feature has been marked as deprecated, and is soon to be replaced by Audio Workers.

    Despite being marked as deprecated for 8 months as of this writing, there exists no appreciable amount of documentation for the successor API, these so-called Audio Workers.

    Vive la web standards !

    Visualize This
    The next problem was visualization. The Web Audio API provides the AnalyzerNode API for accessing both time and frequency domain data from a running audio stream (and fetching the data as both unsigned bytes or floating-point numbers, depending on what the application needs). This is a pretty neat idea. I just wish I could make the API work. The simple demos I could find worked well enough. But when I wired up a prototype to fetch and visualize the time-domain wave, all I got were center-point samples (an array of values that were all 128).

    Even if the API did work, I’m not sure if it would have been that useful. Per my reading of the AnalyserNode API, it only returns data as a single channel. Why would I want that ? My application supports audio with 2 channels. I want 2 channels of data for visualization.

    How To Synchronize
    So I rolled my own visualization solution by maintaining a circular buffer of audio when samples were being generated. Then, requestAnimationFrame() provided the rendering callbacks. The next problem was audio-visual sync. But that certainly is not unique to this situation– maintaining proper A/V sync is a perennial puzzle in real-time multimedia programming. I was able to glean enough timing information from the environment to achieve reasonable A/V sync (verify for yourself).

    Pause/Resume
    The next problem I encountered with the Web Audio API was pause/resume facilities, or the lack thereof. For all its bells and whistles, the API’s omission of such facilities seems most unusual, as if the design philosophy was, “Once the user starts playing audio, they will never, ever have cause to pause the audio.”

    Then again, I must understand that mine is not a use case that the design committee considered and I’m subverting the API in ways the designers didn’t intend. Typical use cases for this API seem to include such workloads as :

    • Downloading, decoding, and playing back a compressed audio stream via the network, applying effects, and visualizing the result
    • Accessing microphone input, applying effects, visualizing, encoding and sending the data across the network
    • Firing sound effects in a gaming application
    • MIDI playback via JavaScript (this honestly amazes me)

    What they did not seem to have in mind was what I am trying to do– synthesize audio in real time.

    I implemented pause/resume in a sub-par manner : pausing has the effect of generating 0 values when the ScriptProcessorNode callback is invoked, while also canceling any animation callbacks. Thus, audio output is technically still occurring, it’s just that the audio is pure silence. It’s not a great solution because CPU is still being used.

    Future Work
    I have a lot more player libraries to port to this new system. But I think I have a good framework set up.

  • avfilter/af_amerge : Cleanup on av_channel_layout_copy() failure

    10 juin 2024, par Michael Niedermayer
    avfilter/af_amerge : Cleanup on av_channel_layout_copy() failure
    

    Fixes : CID1503088 Resource leak

    Sponsored-by : Sovereign Tech Fund
    Signed-off-by : Michael Niedermayer <michael@niedermayer.cc>

    • [DH] libavfilter/af_amerge.c