Recherche avancée

Médias (10)

Mot : - Tags -/wav

Autres articles (27)

  • La file d’attente de SPIPmotion

    28 novembre 2010, par

    Une file d’attente stockée dans la base de donnée
    Lors de son installation, SPIPmotion crée une nouvelle table dans la base de donnée intitulée spip_spipmotion_attentes.
    Cette nouvelle table est constituée des champs suivants : id_spipmotion_attente, l’identifiant numérique unique de la tâche à traiter ; id_document, l’identifiant numérique du document original à encoder ; id_objet l’identifiant unique de l’objet auquel le document encodé devra être attaché automatiquement ; objet, le type d’objet auquel (...)

  • Personnaliser les catégories

    21 juin 2013, par

    Formulaire de création d’une catégorie
    Pour ceux qui connaissent bien SPIP, une catégorie peut être assimilée à une rubrique.
    Dans le cas d’un document de type catégorie, les champs proposés par défaut sont : Texte
    On peut modifier ce formulaire dans la partie :
    Administration > Configuration des masques de formulaire.
    Dans le cas d’un document de type média, les champs non affichés par défaut sont : Descriptif rapide
    Par ailleurs, c’est dans cette partie configuration qu’on peut indiquer le (...)

  • Contribute to documentation

    13 avril 2011

    Documentation is vital to the development of improved technical capabilities.
    MediaSPIP welcomes documentation by users as well as developers - including : critique of existing features and functions articles contributed by developers, administrators, content producers and editors screenshots to illustrate the above translations of existing documentation into other languages
    To contribute, register to the project users’ mailing (...)

Sur d’autres sites (5687)

  • Revision 3327 : Le modèle pour les images prenant en compte les largeurs et autres ...

    25 avril 2010, par kent1 — Log

    Le modèle pour les images prenant en compte les largeurs et autres hauteurs fixées au modèle

  • Discord 24/7 video stream self-bot crashes after a couple hours

    21 juillet 2023, par angelo

    I've implemented this library to make a self-bot that streams videos from a local folder in a loop 24/7 (don't ask me why). I set up an ubuntu vps to run the bot and it works perfectly fine the first 2-3 hours, after that it gets more and more laggy until the server crashes.
pd : It's basically my first time using javascript and stole most of the code from this repo so don't bully me.

    


    Here's the code :

    


    import { Client, TextChannel, CustomStatus, ActivityOptions } from "discord.js-selfbot-v13";
import { command, streamLivestreamVideo, VoiceUdp, setStreamOpts, streamOpts } from "@dank074/discord-video-stream";
import config from "./config.json";
import fs from 'fs';
import path from 'path';

const client = new Client();

client.patchVoiceEvents(); //this is necessary to register event handlers

setStreamOpts(
    config.streamOpts.width,
    config.streamOpts.height,
    config.streamOpts.fps,
    config.streamOpts.bitrateKbps,
    config.streamOpts.hardware_acc
)

const prefix = '$';

const moviesFolder = config.movieFolder || './movies';

const movieFiles = fs.readdirSync(moviesFolder);
let movies = movieFiles.map(file => {
    const fileName = path.parse(file).name;
    // replace space with _
    return { name: fileName.replace(/ /g, ''), path: path.join(moviesFolder, file) };
});
let originalMovList = [...movies];
let movList = movies;
let shouldStop = false;

// print out all movies
console.log(`Available movies:\n${movies.map(m => m.name).join('\n')}`);

const status_idle = () =>  {
    return new CustomStatus()
        .setState('摸鱼进行中')
        .setEmoji('🐟')
}

const status_watch = (name) => {
    return new CustomStatus()
        .setState(`Playing ${name}...`)
        .setEmoji('📽')
}

// ready event
client.on("ready", () => {
    if (client.user) {
        console.log(`--- ${client.user.tag} is ready ---`);
        client.user.setActivity(status_idle() as ActivityOptions)
    }
});

let streamStatus = {
    joined: false,
    joinsucc: false,
    playing: false,
    channelInfo: {
        guildId: '',
        channelId: '',
        cmdChannelId: ''
    },
    starttime: "00:00:00",
    timemark: '',
}

client.on('voiceStateUpdate', (oldState, newState) => {
    // when exit channel
    if (oldState.member?.user.id == client.user?.id) {
        if (oldState.channelId && !newState.channelId) {
            streamStatus.joined = false;
            streamStatus.joinsucc = false;
            streamStatus.playing = false;
            streamStatus.channelInfo = {
                guildId: '',
                channelId: '',
                cmdChannelId: streamStatus.channelInfo.cmdChannelId
            }
            client.user?.setActivity(status_idle() as ActivityOptions)
        }
    }
    // when join channel success
    if (newState.member?.user.id == client.user?.id) {
        if (newState.channelId && !oldState.channelId) {
            streamStatus.joined = true;
            if (newState.guild.id == streamStatus.channelInfo.guildId && newState.channelId == streamStatus.channelInfo.channelId) {
                streamStatus.joinsucc = true;
            }
        }
    }
})

client.on('messageCreate', async (message) => {
    if (message.author.bot) return; // ignore bots
    if (message.author.id == client.user?.id) return; // ignore self
    if (!config.commandChannels.includes(message.channel.id)) return; // ignore non-command channels
    if (!message.content.startsWith(prefix)) return; // ignore non-commands

    const args = message.content.slice(prefix.length).trim().split(/ +/); // split command and arguments
    if (args.length == 0) return;

    const user_cmd = args.shift()!.toLowerCase();

    if (config.commandChannels.includes(message.channel.id)) {
        switch (user_cmd) {
            case 'play':
                playCommand(args, message);
                break;
            case 'stop':
                stopCommand(message);
                break;
            case 'playtime':
                playtimeCommand(message);
                break;
            case 'pause':
                pauseCommand(message);
                break;
            case 'resume':
                resumeCommand(message);
                break;
            case 'list':
                listCommand(message);
                break;
            case 'status':
                statusCommand(message);
                break;
            case 'refresh':
                refreshCommand(message);
                break;
            case 'help':
                helpCommand(message);
                break;
            case 'playall':
                playAllCommand(args, message);
                break;
            case 'stream':
                streamCommand(args, message);
                break;
            case 'shuffle':
                shuffleCommand();
                break;
            case 'skip':
                //skip cmd
                break;
            default:
                message.reply('Invalid command');
        }
    }
});

client.login("TOKEN_HERE");

let lastPrint = "";

async function playAllCommand(args, message) {
    if (streamStatus.joined) {
        message.reply("Already joined");
        return;
    }

    // args = [guildId]/[channelId]
    if (args.length === 0) {
        message.reply("Missing voice channel");
        return;
    }

    // process args
    const [guildId, channelId] = args.shift()!.split("/");
    if (!guildId || !channelId) {
        message.reply("Invalid voice channel");
        return;
    }

    await client.joinVoice(guildId, channelId);
    streamStatus.joined = true;
    streamStatus.playing = false;
    streamStatus.starttime = "00:00:00";
    streamStatus.channelInfo = {
        guildId: guildId,
        channelId: channelId,
        cmdChannelId: message.channel.id,
    };

    const streamUdpConn = await client.createStream();

    streamUdpConn.voiceConnection.setSpeaking(true);
    streamUdpConn.voiceConnection.setVideoStatus(true);

    playAllVideos(streamUdpConn); // Start playing videos

    // Keep the stream open

    streamStatus.joined = false;
    streamStatus.joinsucc = false;
    streamStatus.playing = false;
    lastPrint = "";
    streamStatus.channelInfo = {
        guildId: "",
        channelId: "",
        cmdChannelId: "",
    };
}

async function playAllVideos(udpConn: VoiceUdp) {

    console.log("Started playing video");

    udpConn.voiceConnection.setSpeaking(true);
    udpConn.voiceConnection.setVideoStatus(true);

    try {
        let index = 0;

        while (true) {
            if (shouldStop) {
                break; // For the stop command
            }

            if (index >= movies.length) {
                // Reset the loop
                index = 0;
            }

            const movie = movList[index];

            if (!movie) {
                console.log("Movie not found");
                index++;
                continue;
            }

            let options = {};
            options["-ss"] = "00:00:00";

            console.log(`Playing ${movie.name}...`);

            try {
                let videoStream = streamLivestreamVideo(movie.path, udpConn);
                command?.on('progress', (msg) => {
                    // print timemark if it passed 10 second sionce last print, becareful when it pass 0
                    if (streamStatus.timemark) {
                        if (lastPrint != "") {
                            let last = lastPrint.split(':');
                            let now = msg.timemark.split(':');
                            // turn to seconds
                            let s = parseInt(now[2]) + parseInt(now[1]) * 60 + parseInt(now[0]) * 3600;
                            let l = parseInt(last[2]) + parseInt(last[1]) * 60 + parseInt(last[0]) * 3600;
                            if (s - l >= 10) {
                                console.log(`Timemark: ${msg.timemark}`);
                                lastPrint = msg.timemark;
                            }
                        } else {
                            console.log(`Timemark: ${msg.timemark}`);
                            lastPrint = msg.timemark;
                        }
                    }
                    streamStatus.timemark = msg.timemark;
                });
                const res = await videoStream;
                console.log("Finished playing video " + res);
            } catch (e) {
                console.log(e);
            }

            index++; // Pasar a la siguiente película
        }
    } finally {
        udpConn.voiceConnection.setSpeaking(false);
        udpConn.voiceConnection.setVideoStatus(false);
    }

    command?.kill("SIGINT");
    // send message to channel, not reply
    (client.channels.cache.get(streamStatus.channelInfo.cmdChannelId) as TextChannel).send('Finished playing video, timemark is ' + streamStatus.timemark);
    client.leaveVoice();
    client.user?.setActivity(status_idle() as ActivityOptions)
    streamStatus.joined = false;
    streamStatus.joinsucc = false;
    streamStatus.playing = false;
    lastPrint = ""
    streamStatus.channelInfo = {
        guildId: '',
        channelId: '',
        cmdChannelId: ''
    };
}

function shuffleArray(array) {
    for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
    }
}

function shuffleCommand() {
    shuffleArray(movList);
}

async function playCommand(args, message) {
    if (streamStatus.joined) {
        message.reply('Already joined');
        return;
    }

    // args = [guildId]/[channelId]
    if (args.length == 0) {
        message.reply('Missing voice channel');
        return;
    }

    // process args
    const [guildId, channelId] = args.shift()!.split('/');
    if (!guildId || !channelId) {
        message.reply('Invalid voice channel');
        return;
    }

    // get movie name and find movie file
    let moviename = args.shift()
    let movie = movies.find(m => m.name == moviename);

    if (!movie) {
        message.reply('Movie not found');
        return;
    }

    // get start time from args "hh:mm:ss"
    let startTime = args.shift();
    let options = {}
    // check if start time is valid
    if (startTime) {
        let time = startTime.split(':');
        if (time.length != 3) {
            message.reply('Invalid start time');
            return;
        }
        let h = parseInt(time[0]);
        let m = parseInt(time[1]);
        let s = parseInt(time[2]);
        if (isNaN(h) || isNaN(m) || isNaN(s)) {
            message.reply('Invalid start time');
            return;
        }
        startTime = `${h}:${m}:${s}`;
        options['-ss'] = startTime;
        console.log("Start time: " + startTime);
    }

    await client.joinVoice(guildId, channelId);
    streamStatus.joined = true;
    streamStatus.playing = false;
    streamStatus.starttime = startTime ? startTime : "00:00:00";
    streamStatus.channelInfo = {
        guildId: guildId,
        channelId: channelId,
        cmdChannelId: message.channel.id
    }
    const streamUdpConn = await client.createStream();
    playVideo(movie.path, streamUdpConn, options);
    message.reply('Playing ' + (startTime ? ` from ${startTime} ` : '') + moviename + '...');
    client.user?.setActivity(status_watch(moviename) as ActivityOptions);
}

function stopCommand(message) {
    client.leaveVoice()
    streamStatus.joined = false;
    streamStatus.joinsucc = false;
    streamStatus.playing = false;
    streamStatus.channelInfo = {
        guildId: '',
        channelId: '',
        cmdChannelId: streamStatus.channelInfo.cmdChannelId
    }
    // use sigquit??
    command?.kill("SIGINT");
    // msg
    message.reply('Stopped playing');
    shouldStop = true;
    movList = [...originalMovList];
}

function playtimeCommand(message) {
    // streamStatus.starttime + streamStatus.timemark
    // starttime is hh:mm:ss, timemark is hh:mm:ss.000
    let start = streamStatus.starttime.split(':');
    let mark = streamStatus.timemark.split(':');
    let h = parseInt(start[0]) + parseInt(mark[0]);
    let m = parseInt(start[1]) + parseInt(mark[1]);
    let s = parseInt(start[2]) + parseInt(mark[2]);
    if (s >= 60) {
        m += 1;
        s -= 60;
    }
    if (m >= 60) {
        h += 1;
        m -= 60;
    }
    message.reply(`Play time: ${h}:${m}:${s}`);
}

function pauseCommand(message) {
    if (!streamStatus.playing) {
        command?.kill("SIGSTOP");
        message.reply('Paused');
        streamStatus.playing = false;
    } else {
        message.reply('Not playing');
    }
}

function resumeCommand(message) {
    if (!streamStatus.playing) {
        command?.kill("SIGCONT");
        message.reply('Resumed');
        streamStatus.playing = true;
    } else {
        message.reply('Not playing');
    }
}

function listCommand(message) {
    message.reply(`Available movies:\n${movies.map(m => m.name).join('\n')}`);
}

function statusCommand(message) {
    message.reply(`Joined: ${streamStatus.joined}\nJoin success: ${streamStatus.joinsucc}\nPlaying: ${streamStatus.playing}\nChannel: ${streamStatus.channelInfo.guildId}/${streamStatus.channelInfo.channelId}\nTimemark: ${streamStatus.timemark}\nStart time: ${streamStatus.starttime}`);
}

function refreshCommand(message) {
    // refresh movie list
    const movieFiles = fs.readdirSync(moviesFolder);
    movies = movieFiles.map(file => {
        const fileName = path.parse(file).name;
        // replace space with _
        return { name: fileName.replace(/ /g, ''), path: path.join(moviesFolder, file) };
    });
    message.reply('Movie list refreshed ' + movies.length + ' movies found.\n' + movies.map(m => m.name).join('\n'));
}

function helpCommand(message) {
    // reply all commands here
    message.reply('Available commands:\nplay [guildId]/[channelId] [movie] [start time]\nstop\nlist\nstatus\nrefresh\nplaytime\npause\nresume\nhelp');
}

async function playVideo(video: string, udpConn: VoiceUdp, options: any) {
    console.log("Started playing video");

    udpConn.voiceConnection.setSpeaking(true);
    udpConn.voiceConnection.setVideoStatus(true);
    try {
        let videoStream = streamLivestreamVideo(video, udpConn);
        command?.on('progress', (msg) => {
            // print timemark if it passed 10 second sionce last print, becareful when it pass 0
            if (streamStatus.timemark) {
                if (lastPrint != "") {
                    let last = lastPrint.split(':');
                    let now = msg.timemark.split(':');
                    // turn to seconds
                    let s = parseInt(now[2]) + parseInt(now[1]) * 60 + parseInt(now[0]) * 3600;
                    let l = parseInt(last[2]) + parseInt(last[1]) * 60 + parseInt(last[0]) * 3600;
                    if (s - l >= 10) {
                        console.log(`Timemark: ${msg.timemark}`);
                        lastPrint = msg.timemark;
                    }
                } else {
                    console.log(`Timemark: ${msg.timemark}`);
                    lastPrint = msg.timemark;
                }
            }
            streamStatus.timemark = msg.timemark;
        });
        const res = await videoStream;
        console.log("Finished playing video " + res);
    } catch (e) {
        console.log(e);
    } finally {
        udpConn.voiceConnection.setSpeaking(false);
        udpConn.voiceConnection.setVideoStatus(false);
    }
    command?.kill("SIGINT");
    // send message to channel, not reply
    (client.channels.cache.get(streamStatus.channelInfo.cmdChannelId) as TextChannel).send('Finished playing video, timemark is ' + streamStatus.timemark);
    client.leaveVoice();
    client.user?.setActivity(status_idle() as ActivityOptions)
    streamStatus.joined = false;
    streamStatus.joinsucc = false;
    streamStatus.playing = false;
    lastPrint = ""
    streamStatus.channelInfo = {
        guildId: '',
        channelId: '',
        cmdChannelId: ''
    }
}

async function streamCommand(args, message) {

    if (streamStatus.joined) {
        message.reply('Already joined');
        return;
    }

    // args = [guildId]/[channelId]
    if (args.length == 0) {
        message.reply('Missing voice channel');
        return;
    }

    // process args
    const [guildId, channelId] = args.shift()!.split('/');
    if (!guildId || !channelId) {
        message.reply('Invalid voice channel');
        return;
    }

    let url = args.shift()
    let options = {}

    await client.joinVoice(guildId, channelId);
    streamStatus.joined = true;
    streamStatus.playing = false;
    //streamStatus.starttime = startTime ? startTime : "00:00:00";
    streamStatus.channelInfo = {
        guildId: guildId,
        channelId: channelId,
        cmdChannelId: message.channel.id
    }
    const streamUdpConn = await client.createStream();
    playStream(url, streamUdpConn, options);
    message.reply('Playing url');
    client.user?.setActivity(status_watch('livestream') as ActivityOptions);
}

async function playStream(video: string, udpConn: VoiceUdp, options: any) {
    console.log("Started playing video");

    udpConn.voiceConnection.setSpeaking(true);
    udpConn.voiceConnection.setVideoStatus(true);

    try {
        console.log("Trying to stream url");
        const res = await streamLivestreamVideo(video, udpConn);
        console.log("Finished streaming url");
    } catch (e) {
        console.log(e);
    } finally {
        udpConn.voiceConnection.setSpeaking(false);
        udpConn.voiceConnection.setVideoStatus(false);
    }

    command?.kill("SIGINT");
    client.leaveVoice();
    client.user?.setActivity(status_idle() as ActivityOptions)
    streamStatus.joined = false;
    streamStatus.joinsucc = false;
    streamStatus.playing = false;
    streamStatus.channelInfo = {
        guildId: '',
        channelId: '',
        cmdChannelId: ''
    }

}

// run server if enabled in config
if (config.server.enabled) {
    // run server.js
    require('./server');
}



    


    I've tried running the code with the nocache package, setting up a cron job to clean the cache every 5 minutes, unifying functions in the code, but nothigns works.
I think that the problem has to do with certain process that never really ends after one video finishes playing, probably ffmpeg. I don't know whether is my code, my vps or the library the problem.

    


    I wanted the bot to stay in the voice channel streaming my videos 24/7 (no interruptions), I don't know how to prevent it from getting laggy after a while.

    


    This is the config.json file just in case you wanna test the code and can't find it

    


    {
    "token": "DCTOKEN",
    "videoChannels": ["ID", "OTHERID"],
    "commandChannels": ["ID", "OTHERID"],
    "adminIds": ["ID"],
    "movieFolder": "./movies/",
    "previewCache": "/tmp/preview-cache",
    "streamOpts": {
        "width": 1280,
        "height": 720,
        "fps": 30,
        "bitrateKbps": 3000,
        "hardware_acc": true
    },
    "server": {
        "enabled": false,
        "port": 8080
    }
}



    


  • JavaCV Create Compatible MP4

    15 juin 2017, par Hamish258

    Trying to modify JavaCV 3.2.0 sample https://github.com/bytedeco/javacv/blob/master/samples/WebcamAndMicrophoneCapture.java, to produce an mp4 that quicktime on macOS 10.12.5 can use. Output mp4 works fine with VLC but for the software I’m producing I’d like to minimise users having to install additional products.

    The sample code produces the following output

    [libx264 @ 0x7f927794e200] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX
    [libx264 @ 0x7f927794e200] profile Constrained Baseline, level 3.1
    [libx264 @ 0x7f927794e200] 264 - core 148 - H.264/MPEG-4 AVC codec - Copyleft 2003-2016 - http://www.videolan.org/x264.html - options: cabac=0 ref=1 deblock=0:0:0 analyse=0:0 me=dia subme=0 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=16 chroma_me=1 trellis=0 8x8dct=0 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=0 threads=4 lookahead_threads=4 sliced_threads=1 slices=4 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=0 keyint=60 keyint_min=6 scenecut=0 intra_refresh=0 rc=crf mbtree=0 crf=28.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=0
    Output #0, mp4, to 'alatest.mp4':
     Metadata:
       encoder         : Lavf57.56.100
       Stream #0:0: Video: h264 (Constrained Baseline) ([33][0][0][0] / 0x0021), yuv420p, 1280x720, q=2-31, 2000 kb/s, 15360 tbn
       Stream #0:1: Audio: aac (LC) ([64][0][0][0] / 0x0040), 44100 Hz, stereo fltp, 192 kb/s

    The constrained baseline to 3.1 should produce usable mp4 according to https://trac.ffmpeg.org/wiki/Encode/H.264

    If I use the command line ffmpeg -i alatest.mp4 -pix_fmt yuv420p alantest.mp4 it produces a usable mo4, even though as you can see above yuv420p is the pixel format in use so there’s something else I don’t understand, the code snippet from the sample link is :

       FFmpegFrameRecorder recorder = new FFmpegFrameRecorder("alatest.mp4",1280, 720, 2);
       recorder.setInterleaved(true);
       recorder.setVideoOption("tune", "zerolatency");
       recorder.setVideoOption("preset", "ultrafast");
       recorder.setVideoOption("crf", "28");
       recorder.setVideoBitrate(2000000);
       recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
       recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
       recorder.setFormat("flv");
       recorder.setFrameRate(30);
       recorder.setGopSize(60);

    The command line ffmpeg is displaying

    [libx264 @ 0x7ffca4019400] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX
    [libx264 @ 0x7ffca4019400] profile High, level 3.1
    [libx264 @ 0x7ffca4019400] 264 - core 148 - H.264/MPEG-4 AVC codec - Copyleft 2003-2016 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=6 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
    Output #0, mp4, to 'alantest.mp4':
     Metadata:
       encoder         : Lavf57.71.100
       Stream #0:0: Video: h264 (libx264) ([33][0][0][0] / 0x0021), yuv420p, 1280x720, q=-1--1, 30 fps, 15360 tbn, 30 tbc
       Metadata:
         encoder         : Lavc57.89.100 libx264
       Side data:
         cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: -1
       Stream #0:1: Audio: aac (LC) ([64][0][0][0] / 0x0040), 44100 Hz, stereo, fltp, 128 kb/s
       Metadata:
         encoder         : Lavc57.89.100 aac
    frame=  179 fps= 54 q=-1.0 Lsize=     570kB time=00:00:05.94 bitrate= 786.2kbits/s dup=93 drop=0 speed= 1.8x
    video:470kB audio:93kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 1.341890%

    This is using a High profile and I see q being set differently and tbc. I can’t figure out how to mimic this behaviour in JavaCV, all help greatly appreciated !