Recherche avancée

Médias (1)

Mot : - Tags -/getid3

Autres articles (104)

  • Les tâches Cron régulières de la ferme

    1er décembre 2010, par

    La gestion de la ferme passe par l’exécution à intervalle régulier de plusieurs tâches répétitives dites Cron.
    Le super Cron (gestion_mutu_super_cron)
    Cette tâche, planifiée chaque minute, a pour simple effet d’appeler le Cron de l’ensemble des instances de la mutualisation régulièrement. Couplée avec un Cron système sur le site central de la mutualisation, cela permet de simplement générer des visites régulières sur les différents sites et éviter que les tâches des sites peu visités soient trop (...)

  • Encoding and processing into web-friendly formats

    13 avril 2011, par

    MediaSPIP automatically converts uploaded files to internet-compatible formats.
    Video files are encoded in MP4, Ogv and WebM (supported by HTML5) and MP4 (supported by Flash).
    Audio files are encoded in MP3 and Ogg (supported by HTML5) and MP3 (supported by Flash).
    Where possible, text is analyzed in order to retrieve the data needed for search engine detection, and then exported as a series of image files.
    All uploaded files are stored online in their original format, so you can (...)

  • Formulaire personnalisable

    21 juin 2013, par

    Cette page présente les champs disponibles dans le formulaire de publication d’un média et il indique les différents champs qu’on peut ajouter. Formulaire de création d’un Media
    Dans le cas d’un document de type média, les champs proposés par défaut sont : Texte Activer/Désactiver le forum ( on peut désactiver l’invite au commentaire pour chaque article ) Licence Ajout/suppression d’auteurs Tags
    On peut modifier ce formulaire dans la partie :
    Administration > Configuration des masques de formulaire. (...)

Sur d’autres sites (6057)

  • FFmpeg wrong output duration after av_seek_frame

    18 septembre 2022, par Gogogo

    I try to transcode a video and also cut it, but in the output file, I get the wrong duration for the file(video duration is correct). It happens when I seek the video, as an example, if I try cut from 60000 to 63000 ms I will get :
Format : WebM
Format version : Version 2
File size : 17.6 KiB
Duration : 1 min 4 s
Overall bit rate : 2 232 b/s
Writing application : Lavf59.31.100
Writing library : Lavf59.31.100

    


    Video
ID : 1
Format : VP9
Codec ID : V_VP9
Duration : 2 s 961 ms
Width : 100 pixels
Height : 100 pixels
Display aspect ratio : 1.000
Frame rate mode : Constant
Frame rate : 24.000 FPS
Default : No
Forced : No

    


    Here is my code, what I am doing wrong ?

    


     namespace {&#xA;    &#xA;    constexpr auto maxDurationMs = 3000;&#xA;    constexpr auto maxFileSizeByte = 100000;&#xA;    &#xA;    struct StreamingParams {&#xA;      std::string output_extension;&#xA;      std::string muxer_opt_key;&#xA;      std::string muxer_opt_value;&#xA;      std::string video_codec;&#xA;      std::string codec_priv_key;&#xA;      std::string codec_priv_value;&#xA;    };&#xA;    &#xA;    struct StreamingContext {&#xA;      AVFormatContext* avfc = nullptr;&#xA;      AVCodec* video_avc = nullptr;&#xA;      AVStream* video_avs = nullptr;&#xA;      AVCodecContext* video_avcc = nullptr;&#xA;      int video_index = 0;&#xA;      std::string filename;&#xA;      ~StreamingContext() {}&#xA;    };&#xA;    &#xA;    struct StreamingContextDeleter {&#xA;      void operator()(StreamingContext* context) {&#xA;        if (context) {&#xA;          auto* avfc = &amp;context->avfc;&#xA;          auto* avcc = &amp;context->video_avcc;&#xA;          if (avfc)&#xA;            avformat_close_input(avfc);&#xA;          if (avcc)&#xA;            avcodec_free_context(avcc);&#xA;          if (context->avfc)&#xA;            avformat_free_context(context->avfc);&#xA;        }&#xA;      }&#xA;    };&#xA;    &#xA;    struct AVFrameDeleter {&#xA;      void operator()(AVFrame* frame) {&#xA;        if (frame)&#xA;          av_frame_free(&amp;frame);&#xA;      }&#xA;    };&#xA;    &#xA;    struct AVPacketDeleter {&#xA;      void operator()(AVPacket* packet) {&#xA;        if (packet)&#xA;          av_packet_free(&amp;packet);&#xA;      }&#xA;    };&#xA;    &#xA;    struct SwsContextDeleter {&#xA;      void operator()(SwsContext* context) {&#xA;        if (context)&#xA;          sws_freeContext(context);&#xA;      }&#xA;    };&#xA;    &#xA;    struct AVDictionaryDeleter {&#xA;      void operator()(AVDictionary* dictionary) {&#xA;        if (dictionary)&#xA;          av_dict_free(&amp;dictionary);&#xA;      }&#xA;    };&#xA;    &#xA;    int fill_stream_info(AVStream* avs, AVCodec** avc, AVCodecContext** avcc) {&#xA;      *avc = const_cast(avcodec_find_decoder(avs->codecpar->codec_id));&#xA;      if (!*avc) return -1;&#xA;&#xA;      *avcc = avcodec_alloc_context3(*avc);&#xA;      if (!*avcc)  return -1;&#xA;      if (avcodec_parameters_to_context(*avcc, avs->codecpar) &lt; 0) return -1;&#xA;      if (avcodec_open2(*avcc, *avc, nullptr) &lt; 0) return -1;&#xA;&#xA;      return 0;&#xA;    }&#xA;    &#xA;    int open_media(const char* in_filename, AVFormatContext** avfc) {&#xA;      *avfc = avformat_alloc_context();&#xA;      if (!*avfc) return -1;&#xA;      if (avformat_open_input(avfc, in_filename, nullptr, nullptr) != 0) return -1;&#xA;      if (avformat_find_stream_info(*avfc, nullptr) &lt; 0) return -1;&#xA;    &#xA;      return 0;&#xA;    }&#xA;    &#xA;    int prepare_decoder(std::shared_ptr<streamingcontext> sc) {&#xA;      for (int i = 0; i &lt; sc->avfc->nb_streams; i&#x2B;&#x2B;) {&#xA;        if (sc->avfc->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {&#xA;          sc->video_avs = sc->avfc->streams[i];&#xA;          sc->video_index = i;&#xA;    &#xA;          if (fill_stream_info(sc->video_avs, &amp;sc->video_avc, &amp;sc->video_avcc)) return -1;&#xA;        }&#xA;      }&#xA;    &#xA;      return 0;&#xA;    }&#xA;    &#xA;    int prepare_video_encoder(std::shared_ptr<streamingcontext> sc,&#xA;                              AVCodecContext* decoder_ctx,&#xA;                              AVRational input_framerate,&#xA;                              const StreamingParams&amp; sp) {&#xA;      sc->video_avs = avformat_new_stream(sc->avfc, nullptr);&#xA;    &#xA;      sc->video_avc = const_cast(&#xA;          avcodec_find_encoder_by_name(sp.video_codec.c_str()));&#xA;      if (!sc->video_avc) return -1;&#xA;    &#xA;      sc->video_avcc = avcodec_alloc_context3(sc->video_avc);&#xA;      if (!sc->video_avcc) return -1;&#xA;    &#xA;      av_opt_set(sc->video_avcc->priv_data, "preset", "fast", 0);&#xA;&#xA;      sc->video_avcc->height = 100;&#xA;      sc->video_avcc->width = 100;&#xA;      sc->video_avcc->sample_aspect_ratio = decoder_ctx->sample_aspect_ratio;&#xA;      if (sc->video_avc->pix_fmts)&#xA;        sc->video_avcc->pix_fmt = sc->video_avc->pix_fmts[0];&#xA;      else&#xA;        sc->video_avcc->pix_fmt = decoder_ctx->pix_fmt;&#xA;    &#xA;      constexpr int64_t maxBitrate = maxFileSizeByte / (maxDurationMs / 1000.0) - 1;&#xA;    &#xA;      sc->video_avcc->bit_rate = maxBitrate;&#xA;      sc->video_avcc->rc_buffer_size = decoder_ctx->rc_buffer_size;&#xA;      sc->video_avcc->rc_max_rate = maxBitrate;&#xA;      sc->video_avcc->rc_min_rate = maxBitrate;&#xA;      sc->video_avcc->time_base = av_inv_q(input_framerate);&#xA;      sc->video_avs->time_base = sc->video_avcc->time_base;&#xA;    &#xA;      if (avcodec_open2(sc->video_avcc, sc->video_avc, nullptr) &lt; 0) return -1;&#xA;      avcodec_parameters_from_context(sc->video_avs->codecpar, sc->video_avcc);&#xA;    &#xA;      return 0;&#xA;    }&#xA;    &#xA;    int encode_video(std::shared_ptr<streamingcontext> decoder,&#xA;                     std::shared_ptr<streamingcontext> encoder,&#xA;                     AVFrame* input_frame) {&#xA;      if (input_frame)&#xA;        input_frame->pict_type = AV_PICTURE_TYPE_NONE;&#xA;    &#xA;      AVPacket* output_packet = av_packet_alloc();&#xA;      if (!output_packet) return -1;&#xA;    &#xA;      int response = avcodec_send_frame(encoder->video_avcc, input_frame);&#xA;    &#xA;      while (response >= 0) {&#xA;        response = avcodec_receive_packet(encoder->video_avcc, output_packet);&#xA;        if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {&#xA;          break;&#xA;        } else if (response &lt; 0) return -1;&#xA;    &#xA;        output_packet->stream_index = decoder->video_index;&#xA;        output_packet->duration = encoder->video_avs->time_base.den /&#xA;                                  encoder->video_avs->time_base.num /&#xA;                                  decoder->video_avs->avg_frame_rate.num *&#xA;                                  decoder->video_avs->avg_frame_rate.den;&#xA;    &#xA;        av_packet_rescale_ts(output_packet, decoder->video_avs->time_base,&#xA;                             encoder->video_avs->time_base);&#xA;    &#xA;        response = av_interleaved_write_frame(encoder->avfc, output_packet);&#xA;        if (response != 0) return -1;&#xA;      }&#xA;      av_packet_unref(output_packet);&#xA;      av_packet_free(&amp;output_packet);&#xA;      return 0;&#xA;    }&#xA;    &#xA;    int transcode_video(std::shared_ptr<streamingcontext> decoder,&#xA;                        std::shared_ptr<streamingcontext> encoder,&#xA;                        AVPacket* input_packet,&#xA;                        AVFrame* input_frame) {&#xA;      int response = avcodec_send_packet(decoder->video_avcc, input_packet);&#xA;      if (response &lt; 0) return response;&#xA;&#xA;    &#xA;      while (response >= 0) {&#xA;        response = avcodec_receive_frame(decoder->video_avcc, input_frame);&#xA;        if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {&#xA;          break;&#xA;        } else if (response &lt; 0) return response;&#xA;    &#xA;        if (response >= 0) {&#xA;          if (encode_video(decoder, encoder, input_frame)) return -1;&#xA;        }&#xA;        av_frame_unref(input_frame);&#xA;      }&#xA;    &#xA;      return 0;&#xA;    }&#xA;    &#xA;    }  // namespace&#xA;    &#xA;    &#xA;    int VideoToGifConverter::convert(VideoProp input, QString output) {&#xA;      StreamingParams sp;&#xA;      sp.output_extension = ".webm";&#xA;      sp.video_codec = "libvpx-vp9";&#xA;    &#xA;      auto inputStd = input.path.toStdString();&#xA;      auto outputStd =&#xA;          (output &#x2B; &#x27;/&#x27; &#x2B; QUuid::createUuid().toString(QUuid::StringFormat::Id128))&#xA;              .toStdString() &#x2B;&#xA;          sp.output_extension;&#xA;    &#xA;      auto decoder = std::shared_ptr<streamingcontext>(new StreamingContext,&#xA;                                                       StreamingContextDeleter{});&#xA;      auto encoder = std::shared_ptr<streamingcontext>(new StreamingContext,&#xA;                                                       StreamingContextDeleter{});&#xA;    &#xA;      encoder->filename = std::move(outputStd);&#xA;      decoder->filename = std::move(inputStd);&#xA;    &#xA;      if (open_media(decoder->filename.c_str(), &amp;decoder->avfc))&#xA;        return -1;&#xA;      if (prepare_decoder(decoder))&#xA;        return -1;&#xA;    &#xA;      avformat_alloc_output_context2(&amp;encoder->avfc, nullptr, nullptr,&#xA;                                     encoder->filename.c_str());&#xA;      if (!encoder->avfc) return -1;&#xA;    &#xA;      AVRational input_framerate =&#xA;          av_guess_frame_rate(decoder->avfc, decoder->video_avs, nullptr);&#xA;      prepare_video_encoder(encoder, decoder->video_avcc, input_framerate, sp);&#xA;    &#xA;      if (encoder->avfc->oformat->flags &amp; AVFMT_GLOBALHEADER)&#xA;        encoder->avfc->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;&#xA;&#xA;      if (!(encoder->avfc->oformat->flags &amp; AVFMT_NOFILE)) {&#xA;        if (avio_open(&amp;encoder->avfc->pb, encoder->filename.c_str(),&#xA;                      AVIO_FLAG_WRITE) &lt; 0) return -1;&#xA;      }&#xA;    &#xA;      AVDictionary* muxer_opts = nullptr;&#xA;    &#xA;      if (!sp.muxer_opt_key.empty() &amp;&amp; !sp.muxer_opt_value.empty()) {&#xA;        av_dict_set(&amp;muxer_opts, sp.muxer_opt_key.c_str(),&#xA;                    sp.muxer_opt_value.c_str(), 0);&#xA;      }&#xA;    &#xA;      if (avformat_write_header(encoder->avfc, &amp;muxer_opts) &lt; 0) return -1;&#xA;    &#xA;      auto inputFrame = std::unique_ptr(av_frame_alloc());&#xA;      if (!inputFrame) return -1;&#xA;    &#xA;      auto inputPacket =&#xA;          std::unique_ptr(av_packet_alloc());&#xA;      if (!inputPacket) return -1;&#xA;    &#xA;      auto** streams = decoder->avfc->streams;&#xA;    &#xA;      const auto fps = static_cast<double>(&#xA;                           streams[inputPacket->stream_index]->avg_frame_rate.num) /&#xA;                       streams[inputPacket->stream_index]->avg_frame_rate.den;&#xA;      const size_t beginFrame = input.beginPosMs * fps / 1000;&#xA;      const size_t endFrame = input.endPosMs * fps / 1000;&#xA;      const auto totalFrames = endFrame - beginFrame;&#xA;    &#xA;      size_t count = 0;&#xA;    &#xA;      int64_t startTime =&#xA;          av_rescale_q(input.beginPosMs * AV_TIME_BASE / 1000, {1, AV_TIME_BASE},&#xA;                       decoder->video_avs->time_base);&#xA;    &#xA;      av_seek_frame(decoder->avfc, inputPacket->stream_index, startTime, 0);&#xA;      avcodec_flush_buffers(decoder->video_avcc);&#xA;    &#xA;      while (count &lt; totalFrames &amp;&amp;&#xA;             av_read_frame(decoder->avfc, inputPacket.get()) >= 0) {&#xA;        if (streams[inputPacket->stream_index]->codecpar->codec_type ==&#xA;            AVMEDIA_TYPE_VIDEO) {&#xA;          if (transcode_video(decoder, encoder, inputPacket.get(), inputFrame.get())) {&#xA;            return -1;&#xA;          }&#xA;          &#x2B;&#x2B;count;&#xA;        }&#xA;        av_packet_unref(inputPacket.get());&#xA;      }&#xA;    &#xA;      if (encode_video(decoder, encoder, nullptr, nullptr)) return -1;&#xA;        &#xA;      av_write_trailer(encoder->avfc);&#xA;    &#xA;      return 0;&#xA;    }&#xA;</double></streamingcontext></streamingcontext></streamingcontext></streamingcontext></streamingcontext></streamingcontext></streamingcontext></streamingcontext>

    &#xA;

  • Apostrophe issue with FFmpeg

    1er mars 2024, par Rohan Molinillo

    I'm working on a company's project which is vue.js.&#xA;There are also code parts in php.&#xA;It uses FFmpeg to create a video from multiple videos.&#xA;On each video, there is a text type subtitle.&#xA;Each text is retrieved from a .txt file&#xA;But I have a problem with apostrophes.

    &#xA;

    If in the subtitle is stored like this ( I'm here ) in the txt file, on the video there will be written ( Im ).&#xA;The apostrophe is removed and the rest of the text too ( here ) will not be displayed.

    &#xA;

    I'm new to php and ffmpeg, I've been on this problem for almost 3 weeks.

    &#xA;

    I share the php code with you.

    &#xA;

    &lt;?php&#xA;&#xA;declare(strict_types=1);&#xA;&#xA;array_shift($argv); // remove script name in $argv[0]&#xA;&#xA;$parameters = array_reduce($argv, function ($carry, $arg) {&#xA;    $tokens = explode(&#x27;=&#x27;, $arg);&#xA;    $carry[$tokens[0]] = $tokens[1];&#xA;    return $carry;&#xA;}, []);&#xA;&#xA;$projectPath = $parameters[&#x27;projectPath&#x27;];&#xA;$musicPath = $parameters[&#x27;musicPath&#x27;];&#xA;&#xA;$fontPath = getcwd() . "/public/fonts/cobol/Cobol-Bold.ttf";&#xA;$logoPath = getcwd() . "/public/images/saintex.jpg";&#xA;$carnetLogoPath = getcwd() . "/public/images/CarnetTitre.jpg";&#xA;&#xA;// Adding descriptions for each clip and fade in and fade out filters&#xA;$clipsToDescribe =  glob("$projectPath/*.webm");&#xA;$clipFrameRate = (int) shell_exec("cd $projectPath &amp;&amp; ffprobe -v error -select_streams v -of default=noprint_wrappers=1:nokey=1 -show_entries stream=r_frame_rate $clipsToDescribe[0]");&#xA;$clipFrameRate = $clipFrameRate > 60 ? 30 : $clipFrameRate;&#xA;&#xA;foreach ($clipsToDescribe as $key => $clipToDescribe) {&#xA;    $clipIndex = $key &#x2B; 1;&#xA;    $clipFrames = (int) shell_exec("cd $projectPath &amp;&amp; ffprobe -v error -select_streams v:0 -count_packets -show_entries stream=nb_read_packets -of csv=p=0 $clipToDescribe");&#xA;    $clipDuration = (float) ($clipFrames / $clipFrameRate) - 0.5;&#xA;    file_put_contents("$projectPath/clip{$clipIndex}_desc.txt", addslashes($parameters["clip{$clipIndex}_desc"]));&#xA;    shell_exec("cd $projectPath &amp;&amp; ffmpeg -i $clipToDescribe -vf &#x27;drawtext=fontfile=$fontPath: textfile=clip{$clipIndex}_desc.txt: fontcolor=white: fontsize=46: box=1: boxcolor=black@0.5: boxborderw=5: x=(w-text_w)/2: y=(h-text_h-50): fix_bounds=true, fade=t=in:st=0:d=0.3,fade=t=out:st=$clipDuration:d=0.3&#x27; -b:v 3000K -b:a 192K clip{$clipIndex}.webm");&#xA;}&#xA;array_map(&#x27;unlink&#x27;, glob("$projectPath/*desc.txt"));&#xA;&#xA;shell_exec("cd $projectPath &amp;&amp; ffmpeg -t 2 -f lavfi -i color=c=black:s=1280x720 -r 30 blank.webm");&#xA;shell_exec("cd $projectPath &amp;&amp; ffmpeg -i blank.webm -i $carnetLogoPath -filter_complex &#x27;[0:v][1:v] overlay=(main_w/2)-(overlay_w/2):(main_h/2)-(overlay_h/2)&#x27; -pix_fmt yuv420p -c:a copy logo.webm");&#xA;&#xA;&#xA;&#xA;$workshop = $parameters["workshop_type"];&#xA;$title = $parameters["title"];&#xA;shell_exec("cd $projectPath &amp;&amp; ffmpeg -f lavfi -i color=size=1280x720:duration=3:rate=30:color=black -vf &#x27;drawtext=text=$workshop:fontfile=$fontPath:fontcolor=white:fontsize=46:x=(w-text_w)/2:y=(h-text_h)/2, drawtext=text=$title:fontfile=$fontPath:fontcolor=white:fontsize=46:x=(w-text_w)/2:y=((h-text_h)/2)&#x2B;lh&#x2B;5&#x27; opening.webm");&#xA;unlink("$projectPath/blank.webm");&#xA;&#xA;$videosFile = "file &#x27;logo.webm&#x27;\n";&#xA;$videosFile .= "file &#x27;opening.webm&#x27;\n";{&#xA;    file_put_contents("$projectPath/project_desc.txt", $parameters["project_desc"]);&#xA;    shell_exec("cd $projectPath &amp;&amp; ffmpeg -f lavfi -i color=size=1280x720:duration=3:rate=30:color=black -vf &#x27;drawtext=fontfile=$fontPath:fontsize=46:fontcolor=white:x=(w-text_w)/2:y=(h-text_h)/2:textfile=project_desc.txt&#x27; project_desc.webm");&#xA;    unlink("$projectPath/project_desc.txt");&#xA;    $videosFile .= "file &#x27;project_desc.webm&#x27;\n";&#xA;} &#xA;if(array_key_exists("participants", $parameters)) {&#xA;    file_put_contents("$projectPath/participants.txt", "Participants :\n" . $parameters["participants"]);&#xA;    shell_exec("cd $projectPath &amp;&amp; ffmpeg -f lavfi -i color=size=1280x720:duration=2:rate=30:color=black -vf &#x27;drawtext=fontfile=$fontPath:fontsize=46:fontcolor=white:x=(w-text_w)/2:y=(h-text_h)/2:textfile=participants.txt&#x27; participants.webm");&#xA;    unlink("$projectPath/participants.txt");&#xA;}&#xA;&#xA;$videos =  glob("$projectPath/clip*.webm");&#xA;foreach($videos as $video) {&#xA;    if($video != "originalVideos") {&#xA;        $videosFile .= "file ". "&#x27;{$video}&#x27;\n";&#xA;    }&#xA;} &#xA;if(array_key_exists("participants", $parameters)) {&#xA;    $videosFile .= "file &#x27;$projectPath/participants.webm&#x27;";&#xA;}&#xA;array_map(&#x27;unlink&#x27;, glob("$projectPath/*webm.txt"));&#xA;file_put_contents("$projectPath/videosFile.txt", $videosFile);&#xA;if($musicPath == "/_musics/") {&#xA;    echo(shell_exec("cd $projectPath &amp;&amp; ffmpeg -f concat -safe 0 -i videosFile.txt -b:v 10000K -crf 20 -b:a 192K output.webm"));&#xA;} else {&#xA;    echo(shell_exec("cd $projectPath &amp;&amp; ffmpeg -f concat -safe 0 -i videosFile.txt -b:v 10000K -crf 20 -b:a 192K assembled.webm &amp;&amp; ffmpeg -i assembled.webm -i ../..$musicPath -filter_complex &#x27; [1:0] apad &#x27; -shortest -y -b:v 3000K -b:a 192K output.webm"));&#xA;}&#xA;

    &#xA;

    I tried many things but each time there were errors.&#xA;I think I didn't implement the code properly.

    &#xA;

    I share you the error

    &#xA;

            [09:21:02] RECEIVED EVENT: videoRequest&#xA;{ Error: Command failed: php ./public/src/generate.php projectPath=&#x27;/home/rohan/Documents/dodoc2/_projects/its-a-test&#x27; musicPath=&#x27;/_musics/classic.mp3&#x27; clip1_name=&#x27;&#x27; clip2_name=&#x27;&#x27; clip3_name=&#x27;&#x27; clip4_name=&#x27;&#x27; clip5_name=&#x27;&#x27; clip1_desc=&#x27;It&#x27;s a first test&#x27; clip2_desc=&#x27;It&#x27;s a second test&#x27; clip3_desc=&#x27;It&#x27;s a third test&#x27; clip4_desc=&#x27;It&#x27;s a fourth&#x27; clip5_desc=&#x27;It&#x27;s a last test&#x27; project_desc=&#x27;&#x27; workshop_type=&#x27;Atelier Robotique&#x27; title=&#x27;It&#x27;s a test&#x27; participants=&#x27;Molinillo Rohan&#xA;&#x27;&#xA;PHP Warning:  Undefined array key 1 in /home/rohan/carnet-numerique/public/src/generate.php on line 9&#xA;PHP Warning:  Undefined array key 1 in /home/rohan/carnet-numerique/public/src/generate.php on line 9&#xA;PHP Warning:  Undefined array key 1 in /home/rohan/carnet-numerique/public/src/generate.php on line 9&#xA;PHP Warning:  Undefined array key 1 in /home/rohan/carnet-numerique/public/src/generate.php on line 9&#xA;PHP Warning:  Undefined array key 1 in /home/rohan/carnet-numerique/public/src/generate.php on line 9&#xA;PHP Warning:  Undefined array key 1 in /home/rohan/carnet-numerique/public/src/generate.php on line 9&#xA;ffmpeg version 5.1.1-1ubuntu2.1 Copyright (c) 2000-2022 the FFmpeg developers&#xA;  built with gcc 12 (Ubuntu 12.2.0-3ubuntu1)&#xA;  configuration: --prefix=/usr --extra-version=1ubuntu2.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libdav1d --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libglslang --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librabbitmq --enable-librist --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzimg --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --disable-sndio --enable-pocketsphinx --enable-librsvg --enable-libmfx --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-libplacebo --enable-shared&#xA;  libavutil      57. 28.100 / 57. 28.100&#xA;  libavcodec     59. 37.100 / 59. 37.100&#xA;  libavformat    59. 27.100 / 59. 27.100&#xA;  libavdevice    59.  7.100 / 59.  7.100&#xA;  libavfilter     8. 44.100 /  8. 44.100&#xA;  libswscale      6.  7.100 /  6.  7.100&#xA;  libswresample   4.  7.100 /  4.  7.100&#xA;  libpostproc    56.  6.100 / 56.  6.100&#xA;Input #0, matroska,webm, from &#x27;/home/rohan/Documents/dodoc2/_projects/its-a-test/video-20230404-091933-682.webm&#x27;:&#xA;  Metadata:&#xA;    encoder         : QTmuxingAppLibWebM-0.0.1&#xA;  Duration: N/A, start: -0.001000, bitrate: N/A&#xA;  Stream #0:0(eng): Video: vp8, yuv420p(progressive), 1280x720, SAR 1:1 DAR 16:9, 1k tbr, 1k tbn (default)&#xA;  Stream #0:1(eng): Audio: opus, 48000 Hz, stereo, fltp (default)&#xA;Stream mapping:&#xA;  Stream #0:0 -> #0:0 (vp8 (native) -> vp9 (libvpx-vp9))&#xA;  Stream #0:1 -> #0:1 (opus (native) -> opus (libopus))&#xA;Press [q] to stop, [?] for help&#xA;[libvpx-vp9 @ 0x55952c183000] v1.12.0&#xA;Output #0, webm, to &#x27;clip1.webm&#x27;:&#xA;  Metadata:&#xA;    encoder         : Lavf59.27.100&#xA;  Stream #0:0(eng): Video: vp9, yuv420p(tv, bt470bg/unknown/unknown, progressive), 1280x720 [SAR 1:1 DAR 16:9], q=2-31, 3000 kb/s, 1k fps, 1k tbn (default)&#xA;    Metadata:&#xA;      encoder         : Lavc59.37.100 libvpx-vp9&#xA;    Side data:&#xA;      cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: N/A&#xA;  Stream #0:1(eng): Audio: opus, 48000 Hz, stereo, flt, 192 kb/s (default)&#xA;    Metadata:&#xA;      encoder         : Lavc59.37.100 libopus&#xA;frame=  229 fps= 11 q=12.0 Lsize=    2786kB time=00:00:07.52 bitrate=3034.7kbits/s speed=0.377x    &#xA;video:2601kB audio:181kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.175036%&#xA;PHP Warning:  Undefined array key "clip2_desc" in /home/rohan/carnet-numerique/public/src/generate.php on line 29&#xA;PHP Fatal error:  Uncaught TypeError: addslashes(): Argument #1 ($string) must be of type string, null given in /home/rohan/carnet-numerique/public/src/generate.php:29&#xA;Stack trace:&#xA;#0 /home/rohan/carnet-numerique/public/src/generate.php(29): addslashes()&#xA;#1 {main}&#xA;  thrown in /home/rohan/carnet-numerique/public/src/generate.php on line 29&#xA;&#xA;    at ChildProcess.exithandler (child_process.js:275:12)&#xA;    at emitTwo (events.js:126:13)&#xA;    at ChildProcess.emit (events.js:214:7)&#xA;    at maybeClose (internal/child_process.js:925:16)&#xA;    at Socket.stream.socket.on (internal/child_process.js:346:11)&#xA;    at emitOne (events.js:116:13)&#xA;    at Socket.emit (events.js:211:7)&#xA;    at Pipe._handle.close [as _onclose] (net.js:554:12)&#xA;  killed: false,&#xA;  code: 255,&#xA;  signal: null,&#xA;  cmd: &#x27;php ./public/src/generate.php projectPath=\&#x27;/home/rohan/Documents/dodoc2/_projects/its-a-test\&#x27; musicPath=\&#x27;/_musics/classic.mp3\&#x27; clip1_name=\&#x27;\&#x27; clip2_name=\&#x27;\&#x27; clip3_name=\&#x27;\&#x27; clip4_name=\&#x27;\&#x27; clip5_name=\&#x27;\&#x27; clip1_desc=\&#x27;It\&#x27;s a first test\&#x27; clip2_desc=\&#x27;It\&#x27;s a second test\&#x27; clip3_desc=\&#x27;It\&#x27;s a third test\&#x27; clip4_desc=\&#x27;It\&#x27;s a fourth\&#x27; clip5_desc=\&#x27;It\&#x27;s a last test\&#x27; project_desc=\&#x27;\&#x27; workshop_type=\&#x27;Atelier Robotique\&#x27; title=\&#x27;It\&#x27;s a test\&#x27; participants=\&#x27;Molinillo Rohan\n\&#x27;&#x27; }&#xA;

    &#xA;

  • 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.&#xA;pd : It's basically my first time using javascript and stole most of the code from this repo so don't bully me.

    &#xA;

    Here's the code :

    &#xA;

    import { Client, TextChannel, CustomStatus, ActivityOptions } from "discord.js-selfbot-v13";&#xA;import { command, streamLivestreamVideo, VoiceUdp, setStreamOpts, streamOpts } from "@dank074/discord-video-stream";&#xA;import config from "./config.json";&#xA;import fs from &#x27;fs&#x27;;&#xA;import path from &#x27;path&#x27;;&#xA;&#xA;const client = new Client();&#xA;&#xA;client.patchVoiceEvents(); //this is necessary to register event handlers&#xA;&#xA;setStreamOpts(&#xA;    config.streamOpts.width,&#xA;    config.streamOpts.height,&#xA;    config.streamOpts.fps,&#xA;    config.streamOpts.bitrateKbps,&#xA;    config.streamOpts.hardware_acc&#xA;)&#xA;&#xA;const prefix = &#x27;$&#x27;;&#xA;&#xA;const moviesFolder = config.movieFolder || &#x27;./movies&#x27;;&#xA;&#xA;const movieFiles = fs.readdirSync(moviesFolder);&#xA;let movies = movieFiles.map(file => {&#xA;    const fileName = path.parse(file).name;&#xA;    // replace space with _&#xA;    return { name: fileName.replace(/ /g, &#x27;&#x27;), path: path.join(moviesFolder, file) };&#xA;});&#xA;let originalMovList = [...movies];&#xA;let movList = movies;&#xA;let shouldStop = false;&#xA;&#xA;// print out all movies&#xA;console.log(`Available movies:\n${movies.map(m => m.name).join(&#x27;\n&#x27;)}`);&#xA;&#xA;const status_idle = () =>  {&#xA;    return new CustomStatus()&#xA;        .setState(&#x27;摸鱼进行中&#x27;)&#xA;        .setEmoji(&#x27;&#128031;&#x27;)&#xA;}&#xA;&#xA;const status_watch = (name) => {&#xA;    return new CustomStatus()&#xA;        .setState(`Playing ${name}...`)&#xA;        .setEmoji(&#x27;&#128253;&#x27;)&#xA;}&#xA;&#xA;// ready event&#xA;client.on("ready", () => {&#xA;    if (client.user) {&#xA;        console.log(`--- ${client.user.tag} is ready ---`);&#xA;        client.user.setActivity(status_idle() as ActivityOptions)&#xA;    }&#xA;});&#xA;&#xA;let streamStatus = {&#xA;    joined: false,&#xA;    joinsucc: false,&#xA;    playing: false,&#xA;    channelInfo: {&#xA;        guildId: &#x27;&#x27;,&#xA;        channelId: &#x27;&#x27;,&#xA;        cmdChannelId: &#x27;&#x27;&#xA;    },&#xA;    starttime: "00:00:00",&#xA;    timemark: &#x27;&#x27;,&#xA;}&#xA;&#xA;client.on(&#x27;voiceStateUpdate&#x27;, (oldState, newState) => {&#xA;    // when exit channel&#xA;    if (oldState.member?.user.id == client.user?.id) {&#xA;        if (oldState.channelId &amp;&amp; !newState.channelId) {&#xA;            streamStatus.joined = false;&#xA;            streamStatus.joinsucc = false;&#xA;            streamStatus.playing = false;&#xA;            streamStatus.channelInfo = {&#xA;                guildId: &#x27;&#x27;,&#xA;                channelId: &#x27;&#x27;,&#xA;                cmdChannelId: streamStatus.channelInfo.cmdChannelId&#xA;            }&#xA;            client.user?.setActivity(status_idle() as ActivityOptions)&#xA;        }&#xA;    }&#xA;    // when join channel success&#xA;    if (newState.member?.user.id == client.user?.id) {&#xA;        if (newState.channelId &amp;&amp; !oldState.channelId) {&#xA;            streamStatus.joined = true;&#xA;            if (newState.guild.id == streamStatus.channelInfo.guildId &amp;&amp; newState.channelId == streamStatus.channelInfo.channelId) {&#xA;                streamStatus.joinsucc = true;&#xA;            }&#xA;        }&#xA;    }&#xA;})&#xA;&#xA;client.on(&#x27;messageCreate&#x27;, async (message) => {&#xA;    if (message.author.bot) return; // ignore bots&#xA;    if (message.author.id == client.user?.id) return; // ignore self&#xA;    if (!config.commandChannels.includes(message.channel.id)) return; // ignore non-command channels&#xA;    if (!message.content.startsWith(prefix)) return; // ignore non-commands&#xA;&#xA;    const args = message.content.slice(prefix.length).trim().split(/ &#x2B;/); // split command and arguments&#xA;    if (args.length == 0) return;&#xA;&#xA;    const user_cmd = args.shift()!.toLowerCase();&#xA;&#xA;    if (config.commandChannels.includes(message.channel.id)) {&#xA;        switch (user_cmd) {&#xA;            case &#x27;play&#x27;:&#xA;                playCommand(args, message);&#xA;                break;&#xA;            case &#x27;stop&#x27;:&#xA;                stopCommand(message);&#xA;                break;&#xA;            case &#x27;playtime&#x27;:&#xA;                playtimeCommand(message);&#xA;                break;&#xA;            case &#x27;pause&#x27;:&#xA;                pauseCommand(message);&#xA;                break;&#xA;            case &#x27;resume&#x27;:&#xA;                resumeCommand(message);&#xA;                break;&#xA;            case &#x27;list&#x27;:&#xA;                listCommand(message);&#xA;                break;&#xA;            case &#x27;status&#x27;:&#xA;                statusCommand(message);&#xA;                break;&#xA;            case &#x27;refresh&#x27;:&#xA;                refreshCommand(message);&#xA;                break;&#xA;            case &#x27;help&#x27;:&#xA;                helpCommand(message);&#xA;                break;&#xA;            case &#x27;playall&#x27;:&#xA;                playAllCommand(args, message);&#xA;                break;&#xA;            case &#x27;stream&#x27;:&#xA;                streamCommand(args, message);&#xA;                break;&#xA;            case &#x27;shuffle&#x27;:&#xA;                shuffleCommand();&#xA;                break;&#xA;            case &#x27;skip&#x27;:&#xA;                //skip cmd&#xA;                break;&#xA;            default:&#xA;                message.reply(&#x27;Invalid command&#x27;);&#xA;        }&#xA;    }&#xA;});&#xA;&#xA;client.login("TOKEN_HERE");&#xA;&#xA;let lastPrint = "";&#xA;&#xA;async function playAllCommand(args, message) {&#xA;    if (streamStatus.joined) {&#xA;        message.reply("Already joined");&#xA;        return;&#xA;    }&#xA;&#xA;    // args = [guildId]/[channelId]&#xA;    if (args.length === 0) {&#xA;        message.reply("Missing voice channel");&#xA;        return;&#xA;    }&#xA;&#xA;    // process args&#xA;    const [guildId, channelId] = args.shift()!.split("/");&#xA;    if (!guildId || !channelId) {&#xA;        message.reply("Invalid voice channel");&#xA;        return;&#xA;    }&#xA;&#xA;    await client.joinVoice(guildId, channelId);&#xA;    streamStatus.joined = true;&#xA;    streamStatus.playing = false;&#xA;    streamStatus.starttime = "00:00:00";&#xA;    streamStatus.channelInfo = {&#xA;        guildId: guildId,&#xA;        channelId: channelId,&#xA;        cmdChannelId: message.channel.id,&#xA;    };&#xA;&#xA;    const streamUdpConn = await client.createStream();&#xA;&#xA;    streamUdpConn.voiceConnection.setSpeaking(true);&#xA;    streamUdpConn.voiceConnection.setVideoStatus(true);&#xA;&#xA;    playAllVideos(streamUdpConn); // Start playing videos&#xA;&#xA;    // Keep the stream open&#xA;&#xA;    streamStatus.joined = false;&#xA;    streamStatus.joinsucc = false;&#xA;    streamStatus.playing = false;&#xA;    lastPrint = "";&#xA;    streamStatus.channelInfo = {&#xA;        guildId: "",&#xA;        channelId: "",&#xA;        cmdChannelId: "",&#xA;    };&#xA;}&#xA;&#xA;async function playAllVideos(udpConn: VoiceUdp) {&#xA;&#xA;    console.log("Started playing video");&#xA;&#xA;    udpConn.voiceConnection.setSpeaking(true);&#xA;    udpConn.voiceConnection.setVideoStatus(true);&#xA;&#xA;    try {&#xA;        let index = 0;&#xA;&#xA;        while (true) {&#xA;            if (shouldStop) {&#xA;                break; // For the stop command&#xA;            }&#xA;&#xA;            if (index >= movies.length) {&#xA;                // Reset the loop&#xA;                index = 0;&#xA;            }&#xA;&#xA;            const movie = movList[index];&#xA;&#xA;            if (!movie) {&#xA;                console.log("Movie not found");&#xA;                index&#x2B;&#x2B;;&#xA;                continue;&#xA;            }&#xA;&#xA;            let options = {};&#xA;            options["-ss"] = "00:00:00";&#xA;&#xA;            console.log(`Playing ${movie.name}...`);&#xA;&#xA;            try {&#xA;                let videoStream = streamLivestreamVideo(movie.path, udpConn);&#xA;                command?.on(&#x27;progress&#x27;, (msg) => {&#xA;                    // print timemark if it passed 10 second sionce last print, becareful when it pass 0&#xA;                    if (streamStatus.timemark) {&#xA;                        if (lastPrint != "") {&#xA;                            let last = lastPrint.split(&#x27;:&#x27;);&#xA;                            let now = msg.timemark.split(&#x27;:&#x27;);&#xA;                            // turn to seconds&#xA;                            let s = parseInt(now[2]) &#x2B; parseInt(now[1]) * 60 &#x2B; parseInt(now[0]) * 3600;&#xA;                            let l = parseInt(last[2]) &#x2B; parseInt(last[1]) * 60 &#x2B; parseInt(last[0]) * 3600;&#xA;                            if (s - l >= 10) {&#xA;                                console.log(`Timemark: ${msg.timemark}`);&#xA;                                lastPrint = msg.timemark;&#xA;                            }&#xA;                        } else {&#xA;                            console.log(`Timemark: ${msg.timemark}`);&#xA;                            lastPrint = msg.timemark;&#xA;                        }&#xA;                    }&#xA;                    streamStatus.timemark = msg.timemark;&#xA;                });&#xA;                const res = await videoStream;&#xA;                console.log("Finished playing video " &#x2B; res);&#xA;            } catch (e) {&#xA;                console.log(e);&#xA;            }&#xA;&#xA;            index&#x2B;&#x2B;; // Pasar a la siguiente pel&#xED;cula&#xA;        }&#xA;    } finally {&#xA;        udpConn.voiceConnection.setSpeaking(false);&#xA;        udpConn.voiceConnection.setVideoStatus(false);&#xA;    }&#xA;&#xA;    command?.kill("SIGINT");&#xA;    // send message to channel, not reply&#xA;    (client.channels.cache.get(streamStatus.channelInfo.cmdChannelId) as TextChannel).send(&#x27;Finished playing video, timemark is &#x27; &#x2B; streamStatus.timemark);&#xA;    client.leaveVoice();&#xA;    client.user?.setActivity(status_idle() as ActivityOptions)&#xA;    streamStatus.joined = false;&#xA;    streamStatus.joinsucc = false;&#xA;    streamStatus.playing = false;&#xA;    lastPrint = ""&#xA;    streamStatus.channelInfo = {&#xA;        guildId: &#x27;&#x27;,&#xA;        channelId: &#x27;&#x27;,&#xA;        cmdChannelId: &#x27;&#x27;&#xA;    };&#xA;}&#xA;&#xA;function shuffleArray(array) {&#xA;    for (let i = array.length - 1; i > 0; i--) {&#xA;        const j = Math.floor(Math.random() * (i &#x2B; 1));&#xA;        [array[i], array[j]] = [array[j], array[i]];&#xA;    }&#xA;}&#xA;&#xA;function shuffleCommand() {&#xA;    shuffleArray(movList);&#xA;}&#xA;&#xA;async function playCommand(args, message) {&#xA;    if (streamStatus.joined) {&#xA;        message.reply(&#x27;Already joined&#x27;);&#xA;        return;&#xA;    }&#xA;&#xA;    // args = [guildId]/[channelId]&#xA;    if (args.length == 0) {&#xA;        message.reply(&#x27;Missing voice channel&#x27;);&#xA;        return;&#xA;    }&#xA;&#xA;    // process args&#xA;    const [guildId, channelId] = args.shift()!.split(&#x27;/&#x27;);&#xA;    if (!guildId || !channelId) {&#xA;        message.reply(&#x27;Invalid voice channel&#x27;);&#xA;        return;&#xA;    }&#xA;&#xA;    // get movie name and find movie file&#xA;    let moviename = args.shift()&#xA;    let movie = movies.find(m => m.name == moviename);&#xA;&#xA;    if (!movie) {&#xA;        message.reply(&#x27;Movie not found&#x27;);&#xA;        return;&#xA;    }&#xA;&#xA;    // get start time from args "hh:mm:ss"&#xA;    let startTime = args.shift();&#xA;    let options = {}&#xA;    // check if start time is valid&#xA;    if (startTime) {&#xA;        let time = startTime.split(&#x27;:&#x27;);&#xA;        if (time.length != 3) {&#xA;            message.reply(&#x27;Invalid start time&#x27;);&#xA;            return;&#xA;        }&#xA;        let h = parseInt(time[0]);&#xA;        let m = parseInt(time[1]);&#xA;        let s = parseInt(time[2]);&#xA;        if (isNaN(h) || isNaN(m) || isNaN(s)) {&#xA;            message.reply(&#x27;Invalid start time&#x27;);&#xA;            return;&#xA;        }&#xA;        startTime = `${h}:${m}:${s}`;&#xA;        options[&#x27;-ss&#x27;] = startTime;&#xA;        console.log("Start time: " &#x2B; startTime);&#xA;    }&#xA;&#xA;    await client.joinVoice(guildId, channelId);&#xA;    streamStatus.joined = true;&#xA;    streamStatus.playing = false;&#xA;    streamStatus.starttime = startTime ? startTime : "00:00:00";&#xA;    streamStatus.channelInfo = {&#xA;        guildId: guildId,&#xA;        channelId: channelId,&#xA;        cmdChannelId: message.channel.id&#xA;    }&#xA;    const streamUdpConn = await client.createStream();&#xA;    playVideo(movie.path, streamUdpConn, options);&#xA;    message.reply(&#x27;Playing &#x27; &#x2B; (startTime ? ` from ${startTime} ` : &#x27;&#x27;) &#x2B; moviename &#x2B; &#x27;...&#x27;);&#xA;    client.user?.setActivity(status_watch(moviename) as ActivityOptions);&#xA;}&#xA;&#xA;function stopCommand(message) {&#xA;    client.leaveVoice()&#xA;    streamStatus.joined = false;&#xA;    streamStatus.joinsucc = false;&#xA;    streamStatus.playing = false;&#xA;    streamStatus.channelInfo = {&#xA;        guildId: &#x27;&#x27;,&#xA;        channelId: &#x27;&#x27;,&#xA;        cmdChannelId: streamStatus.channelInfo.cmdChannelId&#xA;    }&#xA;    // use sigquit??&#xA;    command?.kill("SIGINT");&#xA;    // msg&#xA;    message.reply(&#x27;Stopped playing&#x27;);&#xA;    shouldStop = true;&#xA;    movList = [...originalMovList];&#xA;}&#xA;&#xA;function playtimeCommand(message) {&#xA;    // streamStatus.starttime &#x2B; streamStatus.timemark&#xA;    // starttime is hh:mm:ss, timemark is hh:mm:ss.000&#xA;    let start = streamStatus.starttime.split(&#x27;:&#x27;);&#xA;    let mark = streamStatus.timemark.split(&#x27;:&#x27;);&#xA;    let h = parseInt(start[0]) &#x2B; parseInt(mark[0]);&#xA;    let m = parseInt(start[1]) &#x2B; parseInt(mark[1]);&#xA;    let s = parseInt(start[2]) &#x2B; parseInt(mark[2]);&#xA;    if (s >= 60) {&#xA;        m &#x2B;= 1;&#xA;        s -= 60;&#xA;    }&#xA;    if (m >= 60) {&#xA;        h &#x2B;= 1;&#xA;        m -= 60;&#xA;    }&#xA;    message.reply(`Play time: ${h}:${m}:${s}`);&#xA;}&#xA;&#xA;function pauseCommand(message) {&#xA;    if (!streamStatus.playing) {&#xA;        command?.kill("SIGSTOP");&#xA;        message.reply(&#x27;Paused&#x27;);&#xA;        streamStatus.playing = false;&#xA;    } else {&#xA;        message.reply(&#x27;Not playing&#x27;);&#xA;    }&#xA;}&#xA;&#xA;function resumeCommand(message) {&#xA;    if (!streamStatus.playing) {&#xA;        command?.kill("SIGCONT");&#xA;        message.reply(&#x27;Resumed&#x27;);&#xA;        streamStatus.playing = true;&#xA;    } else {&#xA;        message.reply(&#x27;Not playing&#x27;);&#xA;    }&#xA;}&#xA;&#xA;function listCommand(message) {&#xA;    message.reply(`Available movies:\n${movies.map(m => m.name).join(&#x27;\n&#x27;)}`);&#xA;}&#xA;&#xA;function statusCommand(message) {&#xA;    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}`);&#xA;}&#xA;&#xA;function refreshCommand(message) {&#xA;    // refresh movie list&#xA;    const movieFiles = fs.readdirSync(moviesFolder);&#xA;    movies = movieFiles.map(file => {&#xA;        const fileName = path.parse(file).name;&#xA;        // replace space with _&#xA;        return { name: fileName.replace(/ /g, &#x27;&#x27;), path: path.join(moviesFolder, file) };&#xA;    });&#xA;    message.reply(&#x27;Movie list refreshed &#x27; &#x2B; movies.length &#x2B; &#x27; movies found.\n&#x27; &#x2B; movies.map(m => m.name).join(&#x27;\n&#x27;));&#xA;}&#xA;&#xA;function helpCommand(message) {&#xA;    // reply all commands here&#xA;    message.reply(&#x27;Available commands:\nplay [guildId]/[channelId] [movie] [start time]\nstop\nlist\nstatus\nrefresh\nplaytime\npause\nresume\nhelp&#x27;);&#xA;}&#xA;&#xA;async function playVideo(video: string, udpConn: VoiceUdp, options: any) {&#xA;    console.log("Started playing video");&#xA;&#xA;    udpConn.voiceConnection.setSpeaking(true);&#xA;    udpConn.voiceConnection.setVideoStatus(true);&#xA;    try {&#xA;        let videoStream = streamLivestreamVideo(video, udpConn);&#xA;        command?.on(&#x27;progress&#x27;, (msg) => {&#xA;            // print timemark if it passed 10 second sionce last print, becareful when it pass 0&#xA;            if (streamStatus.timemark) {&#xA;                if (lastPrint != "") {&#xA;                    let last = lastPrint.split(&#x27;:&#x27;);&#xA;                    let now = msg.timemark.split(&#x27;:&#x27;);&#xA;                    // turn to seconds&#xA;                    let s = parseInt(now[2]) &#x2B; parseInt(now[1]) * 60 &#x2B; parseInt(now[0]) * 3600;&#xA;                    let l = parseInt(last[2]) &#x2B; parseInt(last[1]) * 60 &#x2B; parseInt(last[0]) * 3600;&#xA;                    if (s - l >= 10) {&#xA;                        console.log(`Timemark: ${msg.timemark}`);&#xA;                        lastPrint = msg.timemark;&#xA;                    }&#xA;                } else {&#xA;                    console.log(`Timemark: ${msg.timemark}`);&#xA;                    lastPrint = msg.timemark;&#xA;                }&#xA;            }&#xA;            streamStatus.timemark = msg.timemark;&#xA;        });&#xA;        const res = await videoStream;&#xA;        console.log("Finished playing video " &#x2B; res);&#xA;    } catch (e) {&#xA;        console.log(e);&#xA;    } finally {&#xA;        udpConn.voiceConnection.setSpeaking(false);&#xA;        udpConn.voiceConnection.setVideoStatus(false);&#xA;    }&#xA;    command?.kill("SIGINT");&#xA;    // send message to channel, not reply&#xA;    (client.channels.cache.get(streamStatus.channelInfo.cmdChannelId) as TextChannel).send(&#x27;Finished playing video, timemark is &#x27; &#x2B; streamStatus.timemark);&#xA;    client.leaveVoice();&#xA;    client.user?.setActivity(status_idle() as ActivityOptions)&#xA;    streamStatus.joined = false;&#xA;    streamStatus.joinsucc = false;&#xA;    streamStatus.playing = false;&#xA;    lastPrint = ""&#xA;    streamStatus.channelInfo = {&#xA;        guildId: &#x27;&#x27;,&#xA;        channelId: &#x27;&#x27;,&#xA;        cmdChannelId: &#x27;&#x27;&#xA;    }&#xA;}&#xA;&#xA;async function streamCommand(args, message) {&#xA;&#xA;    if (streamStatus.joined) {&#xA;        message.reply(&#x27;Already joined&#x27;);&#xA;        return;&#xA;    }&#xA;&#xA;    // args = [guildId]/[channelId]&#xA;    if (args.length == 0) {&#xA;        message.reply(&#x27;Missing voice channel&#x27;);&#xA;        return;&#xA;    }&#xA;&#xA;    // process args&#xA;    const [guildId, channelId] = args.shift()!.split(&#x27;/&#x27;);&#xA;    if (!guildId || !channelId) {&#xA;        message.reply(&#x27;Invalid voice channel&#x27;);&#xA;        return;&#xA;    }&#xA;&#xA;    let url = args.shift()&#xA;    let options = {}&#xA;&#xA;    await client.joinVoice(guildId, channelId);&#xA;    streamStatus.joined = true;&#xA;    streamStatus.playing = false;&#xA;    //streamStatus.starttime = startTime ? startTime : "00:00:00";&#xA;    streamStatus.channelInfo = {&#xA;        guildId: guildId,&#xA;        channelId: channelId,&#xA;        cmdChannelId: message.channel.id&#xA;    }&#xA;    const streamUdpConn = await client.createStream();&#xA;    playStream(url, streamUdpConn, options);&#xA;    message.reply(&#x27;Playing url&#x27;);&#xA;    client.user?.setActivity(status_watch(&#x27;livestream&#x27;) as ActivityOptions);&#xA;}&#xA;&#xA;async function playStream(video: string, udpConn: VoiceUdp, options: any) {&#xA;    console.log("Started playing video");&#xA;&#xA;    udpConn.voiceConnection.setSpeaking(true);&#xA;    udpConn.voiceConnection.setVideoStatus(true);&#xA;&#xA;    try {&#xA;        console.log("Trying to stream url");&#xA;        const res = await streamLivestreamVideo(video, udpConn);&#xA;        console.log("Finished streaming url");&#xA;    } catch (e) {&#xA;        console.log(e);&#xA;    } finally {&#xA;        udpConn.voiceConnection.setSpeaking(false);&#xA;        udpConn.voiceConnection.setVideoStatus(false);&#xA;    }&#xA;&#xA;    command?.kill("SIGINT");&#xA;    client.leaveVoice();&#xA;    client.user?.setActivity(status_idle() as ActivityOptions)&#xA;    streamStatus.joined = false;&#xA;    streamStatus.joinsucc = false;&#xA;    streamStatus.playing = false;&#xA;    streamStatus.channelInfo = {&#xA;        guildId: &#x27;&#x27;,&#xA;        channelId: &#x27;&#x27;,&#xA;        cmdChannelId: &#x27;&#x27;&#xA;    }&#xA;&#xA;}&#xA;&#xA;// run server if enabled in config&#xA;if (config.server.enabled) {&#xA;    // run server.js&#xA;    require(&#x27;./server&#x27;);&#xA;}&#xA;&#xA;

    &#xA;

    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.&#xA;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.

    &#xA;

    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.

    &#xA;

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

    &#xA;

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

    &#xA;