Recherche avancée

Médias (2)

Mot : - Tags -/kml

Autres articles (31)

  • Personnaliser en ajoutant son logo, sa bannière ou son image de fond

    5 septembre 2013, par

    Certains thèmes prennent en compte trois éléments de personnalisation : l’ajout d’un logo ; l’ajout d’une bannière l’ajout d’une image de fond ;

  • Ecrire une actualité

    21 juin 2013, par

    Présentez les changements dans votre MédiaSPIP ou les actualités de vos projets sur votre MédiaSPIP grâce à la rubrique actualités.
    Dans le thème par défaut spipeo de MédiaSPIP, les actualités sont affichées en bas de la page principale sous les éditoriaux.
    Vous pouvez personnaliser le formulaire de création d’une actualité.
    Formulaire de création d’une actualité Dans le cas d’un document de type actualité, les champs proposés par défaut sont : Date de publication ( personnaliser la date de publication ) (...)

  • Soumettre améliorations et plugins supplémentaires

    10 avril 2011

    Si vous avez développé une nouvelle extension permettant d’ajouter une ou plusieurs fonctionnalités utiles à MediaSPIP, faites le nous savoir et son intégration dans la distribution officielle sera envisagée.
    Vous pouvez utiliser la liste de discussion de développement afin de le faire savoir ou demander de l’aide quant à la réalisation de ce plugin. MediaSPIP étant basé sur SPIP, il est également possible d’utiliser le liste de discussion SPIP-zone de SPIP pour (...)

Sur d’autres sites (4845)

  • Announcing Matomo 4 : More security, privacy and better performance

    17 novembre 2020, par Matomo Core Team — Community, Development, Privacy, Security

    The moment we’ve all been waiting for is here … Matomo Analytics 4 has launched !! We’re incredibly grateful for all community members and contributors who’ve helped with improvements, and our awesome team for all the fixes. 

    We can’t wait for you to gain greater security, privacy protection, and be able to boost your website performance. Now who’s ready ?

    Minimise your business’ web data security risk

    We’ve made Matomo even more secure to meet our users’ ever increasing security needs. Matomo 4 has certainly delivered on these expectations with a wide range of security enhancements and fixes across the platform :

    • Support for app specific API tokens. [#6559]
    • API tokens and session ids are now stored hashed in the database which means if someone can access your database they wouldn’t be able to get the actual token.
    • A more secure host validation. [#16169]
    • By default, you no longer can embed widgets through tokens with higher privileges. [#16264]
    • Plenty of other minor security fixes.

    More protection of your customer’s personal data

    Matomo 4 ensures you’re compliant with data privacy laws and provides you with more ways to keep your customer’s personal data private, such as :

    • The ability to automatically anonymise the referrer to avoid tracking personal data by accident. [#15426]
    • The option to enforce the disabling of cookies. [#16258]
    • Possibility in JavaScript tracker to turn cookies on and off at any time. [#13056]
    • The option to not store any IP address at all. [#16377]
    • Easily disable visits log and visitor profile feature if needed for privacy compliance [#16259]
    • New segment to separate visitors who gave consent vs visitors who didn’t give consent. [#16192]

    Matomo now offers PHP 8 support to users. Want to know more ? Get a detailed list of over 300 fixes and improvements in the Matomo 4 changelog.

    Increased conversion rates with a focus on page performance

    Our new Page Performance feature in Matomo 4 can help you increase conversion rates by showing you exactly how fast or slow your website is going, and WHY. An Akamai Online Retail Study in 2017 found that a 100-millisecond delay in website load time could underperform website conversion rates by up to 7%. 

    By using this new feature you can quickly identify slow pages and fix page speed issues as soon as they arise, meaning you never miss out on those valuable new sales opportunities.

    Improve your Google search rankings in 2021

    According to moz.com, Google’s bringing in a new ranking factor into their algorithm named Core Web Vitals, which will place greater emphasis on load speed (favouring websites that load faster). This means the slower your page loads, the worse it will rank in Google. With Matomo’s new feature, you’ll be able to optimise your pages to rank better according to the Core Web Vitals ranking factor. 

    Read more on how you can use this new feature : https://matomo.org/faq/how-to/how-do-i-see-page-performance-reports/

    Need help upgrading Matomo ?

    Read the Updating Matomo user guide or contact the Matomo experts

    Please note : It may take a while for you to receive a notice to update to Matomo 4.

  • Why does my ffmpeg audio sound slower and deeper - sample rate mismatch

    4 septembre 2020, par yogesh zinzu

    ok so this is a discord bot to record voice chat
https://hatebin.com/hgjlazacri
Now the bot works perfectly fine but the issue is that the audio sounds a bit deeper and slower than normal.. Why does it happen ? how can I make the audio sound 1:1..

    


    

    

    const Discord = require('discord.js');
const client = new Discord.Client();
const ffmpegInstaller = require('@ffmpeg-installer/ffmpeg');
const ffmpeg = require('fluent-ffmpeg');
ffmpeg.setFfmpegPath(ffmpegInstaller.path);
const fs = require('fs-extra')
const mergeStream = require('merge-stream');
const config = require('./config.json');
const { getAudioDurationInSeconds } = require('get-audio-duration');
const cp = require('child_process');
const path1 = require('path');
const Enmap = require('enmap');
const UserRecords = require("./models/userrecords.js")
const ServerRecords = require("./models/serverrecords.js")
let prefix = `$`
class Readable extends require('stream').Readable { _read() {} }
let recording = false;
let currently_recording = {};
let mp3Paths = [];
const silence_buffer = new Uint8Array(3840);
const express = require('express')
const app = express()
const port = 3000
const publicIP = require('public-ip')
const { program } = require('commander');
const { path } = require('@ffmpeg-installer/ffmpeg');
const version = '0.0.1'
program.version(version);
let debug = false
let runProd = false
let fqdn = "";
const mongoose = require("mongoose");
const MongoClient = require('mongodb').MongoClient;
mongoose.connect('SECRRET',{
  useNewUrlParser: true
}, function(err){
  if(err){
    console.log(err);
  }else{
    console.log("Database connection initiated");
  }
});
require("dotenv").config()
function bufferToStream(buffer) {
    let stream = new Readable();
    stream.push(buffer);
    return stream;
}





client.commands = new Enmap();

client.on('ready', async () => {
    console.log(`Logged in as ${client.user.tag}`);

    let host = "localhost"

    

    let ip = await publicIP.v4();

    let protocol = "http";
    if (!runProd) {
        host = "localhost"
    } else {
        host = `35.226.244.186`;
    }
    fqdn = `${protocol}://${host}:${port}`
    app.listen(port, `0.0.0.0`, () => {
        console.log(`Listening on port ${port} for ${host} at fqdn ${fqdn}`)
    })
});
let randomArr = []
let finalArrWithIds = []
let variable = 0
client.on('message', async message => {
    console.log(`fuck`);
    if(message.content === `$record`){
        mp3Paths = []
        finalArrWithIds = []
        let membersToScrape = Array.from(message.member.voice.channel.members.values());
        membersToScrape.forEach((member) => {
            if(member.id === `749250882830598235`) {
                console.log(`botid`);
            }
            else {
                finalArrWithIds.push(member.id)
            }
            
        })
        const randomNumber = Math.floor(Math.random() * 100)
        randomArr = []
        randomArr.push(randomNumber)
    }
   
    
    const generateSilentData = async (silentStream, memberID) => {
        console.log(`recordingnow`)
        while(recording) {
            if (!currently_recording[memberID]) {
                silentStream.push(silence_buffer);
            }
            await new Promise(r => setTimeout(r, 20));
        }
        return "done";
    }
    console.log(generateSilentData, `status`)
    function generateOutputFile(channelID, memberID) {
        const dir = `./recordings/${channelID}/${memberID}`;
        fs.ensureDirSync(dir);
        const fileName = `${dir}/${randomArr[0]}.aac`;
        console.log(`${fileName} ---------------------------`);
        return fs.createWriteStream(fileName);
    }
    
    if (!fs.existsSync("public")) {
        fs.mkdirSync("public");
    }
    app.use("/public", express.static("./public"));
  if (!message.guild) return;

  if (message.content === config.prefix + config.record_command) {
    if (recording) {
        message.reply("bot is already recording");
        return
    }
    if (message.member.voice.channel) {
        recording = true;
        const connection = await message.member.voice.channel.join();
        const dispatcher = connection.play('./audio.mp3');

        connection.on('speaking', (user, speaking) => {
            if (speaking.has('SPEAKING')) {
                currently_recording[user.id] = true;
            } else {
                currently_recording[user.id] = false;
            }
        })


        let members = Array.from(message.member.voice.channel.members.values());
        members.forEach((member) => {

            if (member.id != client.user.id) {
                let memberStream = connection.receiver.createStream(member, {mode : 'pcm', end : 'manual'})

                let outputFile = generateOutputFile(message.member.voice.channel.id, member.id);
                console.log(outputFile, `outputfile here`);
                mp3Paths.push(outputFile.path);
                    

                silence_stream = bufferToStream(new Uint8Array(0));
                generateSilentData(silence_stream, member.id).then(data => console.log(data));
                let combinedStream = mergeStream(silence_stream, memberStream);

                ffmpeg(combinedStream)
                    .inputFormat('s32le')
                    .audioFrequency(44100)
                    .audioChannels(2)
                    .on('error', (error) => {console.log(error)})
                    .audioCodec('aac')
                    .format('adts') 
                    .pipe(outputFile)
                    
            }
        })
    } else {
      message.reply('You need to join a voice channel first!');
    }
  }

  if (message.content === config.prefix + config.stop_command) {

    let date = new Date();
    let dd = String(date.getDate()).padStart(2, '0');
    let mm = String(date.getMonth() + 1).padStart(2, '0'); 
    let yyyy = date.getFullYear();
    date = mm + '/' + dd + '/' + yyyy;





    let currentVoiceChannel = message.member.voice.channel;
    if (currentVoiceChannel) {
        recording = false;
        await currentVoiceChannel.leave();

        let mergedOutputFolder = './recordings/' + message.member.voice.channel.id + `/${randomArr[0]}/`;
        fs.ensureDirSync(mergedOutputFolder);
        let file_name = `${randomArr[0]}` + '.aac';
        let mergedOutputFile = mergedOutputFolder + file_name;
    
        
    let download_path = message.member.voice.channel.id + `/${randomArr[0]}/` + file_name;

        let mixedOutput = new ffmpeg();
        console.log(mp3Paths, `mp3pathshere`);
        mp3Paths.forEach((mp3Path) => {
             mixedOutput.addInput(mp3Path);
            
        })
        console.log(mp3Paths);
        //mixedOutput.complexFilter('amix=inputs=2:duration=longest');
        mixedOutput.complexFilter('amix=inputs=' + mp3Paths.length + ':duration=longest');
        
        let processEmbed = new Discord.MessageEmbed().setTitle(`Audio Processing.`)
        processEmbed.addField(`Audio processing starting now..`, `Processing Audio`)
        processEmbed.setThumbnail(`https://media.discordapp.net/attachments/730811581046325348/748610998985818202/speaker.png`)
        processEmbed.setColor(` #00FFFF`)
        const processEmbedMsg = await message.channel.send(processEmbed)
        async function saveMp3(mixedData, outputMixed) {
            console.log(`${mixedData} MIXED `)
            
            
            
            return new Promise((resolve, reject) => {
                mixedData.on('error', reject).on('progress',
                async (progress) => {
                    
                    let processEmbedEdit = new Discord.MessageEmbed().setTitle(`Audio Processing.`)
                    processEmbedEdit.addField(`Processing: ${progress.targetSize} KB converted`, `Processing Audio`)
                    processEmbedEdit.setThumbnail(`https://media.discordapp.net/attachments/730811581046325348/748610998985818202/speaker.png`)
                    processEmbedEdit.setColor(` #00FFFF`)
                    processEmbedMsg.edit(processEmbedEdit)
                    console.log('Processing: ' + progress.targetSize + ' KB converted');
                }).on('end', () => {
                    console.log('Processing finished !');
                    resolve()
                }).saveToFile(outputMixed);
                console.log(`${outputMixed} IT IS HERE`);
            })
        }
        // mixedOutput.saveToFile(mergedOutputFile);
        await saveMp3(mixedOutput, mergedOutputFile);
        console.log(`${mixedOutput} IN HEREEEEEEE`);
        // We saved the recording, now copy the recording
        if (!fs.existsSync(`./public`)) {
            fs.mkdirSync(`./public`);
        }
        let sourceFile = `${__dirname}/recordings/${download_path}`
        console.log(`DOWNLOAD PATH HERE ${download_path}`)
        const guildName = message.guild.id;
        const serveExist = `/public/${guildName}`
        if (!fs.existsSync(`.${serveExist}`)) {
            fs.mkdirSync(`.${serveExist}`)
        }
        let destionationFile = `${__dirname}${serveExist}/${file_name}`

        let errorThrown = false
        try {
            fs.copySync(sourceFile, destionationFile);
        } catch (err) {
            errorThrown = true
            await message.channel.send(`Error: ${err.message}`)
        }
        const usersWithTag = finalArrWithIds.map(user => `\n <@${user}>`);
        let timeSpent = await getAudioDurationInSeconds(`public/${guildName}/${file_name}`)
        let timesSpentRound = Math.floor(timeSpent)
        let finalTimeSpent = timesSpentRound / 60
        let finalTimeForReal = Math.floor(finalTimeSpent)
        if(!errorThrown){
            //--------------------- server recording save START
            class GeneralRecords {
                constructor(generalLink, date, voice, time) {
                  this.generalLink = generalLink;
                  this.date = date;
                  this.note = `no note`;
                  this.voice = voice;
                  this.time = time
                }
              }
              let newGeneralRecordClassObject = new GeneralRecords(`${fqdn}/public/${guildName}/${file_name}`, date, usersWithTag, finalTimeForReal)
              let checkingServerRecord = await ServerRecords.exists({userid: `server`})
              if(checkingServerRecord === true){
                  existingServerRecord = await ServerRecords.findOne({userid: `server`})
                  existingServerRecord.content.push(newGeneralRecordClassObject)
                  await existingServerRecord.save()
              }
              if(checkingServerRecord === false){
                let serverRecord = new ServerRecords()
                serverRecord.userid = `server`
                serverRecord.content.push(newGeneralRecordClassObject)
                await serverRecord.save()
              }
              //--------------------- server recording save STOP
        }
        
        //--------------------- personal recording section START
        for( member of finalArrWithIds) {

        let personal_download_path = message.member.voice.channel.id + `/${member}/` + file_name;
        let sourceFilePersonal = `${__dirname}/recordings/${personal_download_path}`
        let destionationFilePersonal = `${__dirname}${serveExist}/${member}/${file_name}`
        await fs.copySync(sourceFilePersonal, destionationFilePersonal);
        const user = client.users.cache.get(member);
        console.log(user, `user here`);
        try {
            ffmpeg.setFfmpegPath(ffmpegInstaller.path);
          
            ffmpeg(`public/${guildName}/${member}/${file_name}`)
             .audioFilters('silenceremove=stop_periods=-1:stop_duration=1:stop_threshold=-90dB')
             .output(`public/${guildName}/${member}/personal-${file_name}`)
             .on(`end`, function () {
               console.log(`DONE`);
             })
             .on(`error`, function (error) {
               console.log(`An error occured` + error.message)
             })
             .run();
             
          }
          catch (error) {
          console.log(error)
          }
        

        // ----------------- SAVING PERSONAL RECORDING TO DATABASE START
        class PersonalRecords {
            constructor(generalLink, personalLink, date, time) {
              this.generalLink = generalLink;
              this.personalLink = personalLink;
              this.date = date;
              this.note = `no note`;
              this.time = time;
            }
          }
          let timeSpentPersonal = await getAudioDurationInSeconds(`public/${guildName}/${file_name}`)
          let timesSpentRoundPersonal = Math.floor(timeSpentPersonal)
          let finalTimeSpentPersonal = timesSpentRoundPersonal / 60
          let finalTimeForRealPersonal = Math.floor(finalTimeSpentPersonal)
          let newPersonalRecordClassObject = new PersonalRecords(`${fqdn}/public/${guildName}/${file_name}`, `${fqdn}/public/${guildName}/${member}/personal-${file_name}`, date, finalTimeForRealPersonal)

           let checkingUserRecord = await UserRecords.exists({userid: member})
              if(checkingUserRecord === true){
                  existingUserRecord = await UserRecords.findOne({userid: member})
                  existingUserRecord.content.push(newPersonalRecordClassObject)
                  await existingUserRecord.save()
              }
              if(checkingUserRecord === false){
                let newRecord = new UserRecords()
                newRecord.userid = member
                newRecord.content.push(newPersonalRecordClassObject)
                await newRecord.save()
              }


       
        // ----------------- SAVING PERSONAL RECORDING TO DATABASE END
       

        const endPersonalEmbed = new Discord.MessageEmbed().setTitle(`Your performance was amazing ! Review it here :D`)
        endPersonalEmbed.setColor('#9400D3')
        endPersonalEmbed.setThumbnail(`https://media.discordapp.net/attachments/730811581046325348/745381641324724294/vinyl.png`)
        endPersonalEmbed.addField(`1
  • Spotlight : Alwaysdata.com the company behind Piwik.org web hosting [Interview]

    11 avril 2013, par matt — About, Community

    Piwik is the result of the work of many talented individuals and companies. Today we’d like to showcase Alwaysdata.com, the awesome web hosting company providing managed hosting for all Piwik.org websites and services.

    I recently met and asked a few questions to Cyril, co-founder of Alwaysdata.com and Piwik core developer. Learn more in the interview below !

    What is Alwaysdata ?

    We are a French web hosting company created in 2006. If you need to host a website — a Piwik installation, for example — or even your domains/emails, we provide infrastructure and maintenance services.

    Who are your customers and what kind of work do you do ?

    We have several types of clients :

    • Individuals who need hosting for their personal site and who benefit from storage space with direct SSH access.
    • Web agencies who need hosting for their clients’ sites.
    • The largest customers, often on dedicated servers, for hosting their site/infrastructure.

    Our work falls into three categories :

    1. Support (via administration, telephone, Twitter, IRC, etc.)
    2. Development (in Python), primarily to add new features
    3. System administration, either for maintenance (e.g. adding servers), or for preparing new features

    What sets Alwaysdata apart from the large web hosting competition ?

    Two things :

    • Availability. We are a small team and often know our customers quite well. We are all on IRC, so you can contact us directly if you need any assistance.
    • Features. We are halfway between traditional web hosting and the cloud, combining the advantages of both.

    Are you using Piwik internally or with customers ? If so, how are you using Piwik ?

    All of our customers can view statistics for their sites via our global Piwik installation, without having to configure anything.

    To provide these analytics reports to our customers, we implemented import of the raw access logs in Piwik. The Log import toolkit is now a feature included in Piwik.

    What is the next big thing for Alwaysdata ?

    We are going to upgrade our pricing : instead of fixed costs, each of our clients will now pay exactly what they consume. This allows our clients the benefit of a very high quality service for the lowest possible price.

    We are also going to add native support for more technologies : Java, Node.js, ZeroMQ, etc.

    Thank you for your time and all the best to Alwaysdata for the future !

    Note from Matt, Piwik founder : Cyril and the team at Alwaysdata.com have been consistently great in their system administration work for Piwik.org services, providing a fast and reliable web hosting experience with top notch support and security practises. They also handled the migration of all services from our old servers with total piece of mind.

    Alwaysdata contributed to Piwik the popular Log Analytics toolkit. They are great software developers and system administrators with a passion for their work. Since 2006, they have been maintaining optimized hosting services for the entire web infrastructure (websites, domains, emails, databases, etc.), from the simplest to the most exotic. We do recommend their managed hosting services.

    Learn more