How to prevent my site from falling, when running a "heavy" script?

Asked

Viewed 212 times

1

I have a script that goes through a directory looking for video files in it and then I use the shell_exec with the ffmpeg to convert the same, the problem is that my site is falling while running the script, after booting the same on the server, the site falls and cannot access until I terminate the script, I am using the Wamp installed on a Windows Server 2012.

I think maybe the problem is in memory_limit in PHP.ini which is in 128m, but not sure, there is some solution to prevent my site from falling during that process?

This is my summary script:

if($handle = opendir($diretorio)){
    while ($entry = readdir($handle)){
        $ext = strtolower(pathinfo($entry, PATHINFO_EXTENSION));
        if(in_array($ext, $types)){
            $ep = explode('.', $entry);

            $input = $diretorio.$entry;

            $cmd = $ffmpeg.' -i '.$input.' -hide_banner 2>&1 &';
            $exec = shell_exec($cmd);
            $data = trim($exec);
            $x = getStreams($data);

            $video_key = array_search('Video', array_column($x, 'formato'));
            $video_map = $x[$video_key]["tempo"];
            foreach ($x as $index => $value){

                #esse if se repete mais 4x procurando outros formatos e/ou idiomas
                if($value["formato"] === "Audio" && ($value["idioma"] === "jpn" || $value["idioma"] === "eng")){
                    $audio_map = $value["tempo"];
                    $output_legendado = $dir_original_saida.$ep["0"].".mp4";

                    if (!is_dir($dir_original_saida)) {
                        mkdir($dir_original_saida, 0777, true);
                    }
                    if(!file_exists($output_legendado)){
                        $query = " -sn -map $video_map -map $audio_map -vcodec libx264 -acodec aac -ab 128k -y -movflags +faststart $output_legendado ";
                    }
                }           
            }
            $cmd_con = $ffmpeg." -i $input $query 2>&1 &";
            $out = exec($cmd_con);
            echo "<pre>";
            print_r($out);
            echo "</pre>";      
        }
    }
    closedir($handle);
}
  • Ever tried running the code on the command line? It’s always good to separate the presentation part of your page from various routines. Make your code more testable and modularized, so you’ll know what your limits are

  • Do you have an example of how I can run this code on the @Jeffersonquesado command line

  • I’ll need more space than available in comment, wait

2 answers

1

The first point I see is to try to make your code more testable, separate it into smaller units to know how each of them behaves, how much it needs, etc.

I see here that you iterate over a directory, decide if it is a file to treat and, being this desirable file, check if you need query additional, creating a folder if there is no. I don’t know what the ffmpeg ' -i '.$input.' -hide_banner does, but

Hence, I come to the conclusion that you need a list of functions that can facilitate your life by modularizing the code.

// Numa abordagem top-down, as funções não declaradas estão abaixo

function transforma_diretorio_filmes($diretorio) {
    $retornos = array();
    if ($handle = opendir($diretorio)) {
        while ($entry = readdir($handle)) {
            if (arquivo_interessante($entry)) {
                $retornos = executa_ffmpeg($diretorio, $entry);
            }
        }
    }
    return $retornos;
}

function arquivo_interessante($entry) {
     $ext = strtolower(pathinfo($entry, PATHINFO_EXTENSION));
     return in_array($ext, $types);
}

function executa_ffmpeg($diretorio, $entry) {
    $query = gera_query($diretorio, $entry);
    $cmd_con = $ffmpeg." -i $diretorio.$entry $query 2>&1 &";
    return exec($cmd_con);
}

function gera_query($diretorio, $entry) {
    $query = "";
    $input = $diretorio.$entry;
    $ep = explode('.', $entry);

    $x = getStreamsFromFFMPEG($input);
    $video_key = array_search('Video', array_column($x, 'formato'));
    $video_map = $x[$video_key]["tempo"];
    foreach ($x as $index => $value){

        #esse if se repete mais 4x procurando outros formatos e/ou idiomas
        if (formato_desejado($value)) {
            $audio_map = $value["tempo"];
            $output_legendado = $dir_original_saida.$ep["0"].".mp4";
            verifica_dir_saida($dir_original_saida);
            if (!file_exists($output_legendado)) {
                $query = " -sn -map $video_map -map $audio_map -vcodec libx264 -acodec aac -ab 128k -y -movflags +faststart $output_legendado ";
            }
        }
    }
    return $query;
}

function getStreamsFromFFMPEG($input) {
    $cmd = $ffmpeg.' -i '.$input.' -hide_banner 2>&1 &';
    $exec = shell_exec($cmd);
    $data = trim($exec);
    return getStreams($data);
}

function formato_desejado($value) {
    return $value["formato"] === "Audio" && ($value["idioma"] === "jpn" || $value["idioma"] === "eng");
}

function verifica_dir_saida($dir_original_saida) {
    if (!is_dir($dir_original_saida)) {
        mkdir($dir_original_saida, 0777, true);
    }
}

Note that it is the same code that you posted, but more sliced into smaller and more palatable pieces, each at a level of abstraction more suitable than all together. If these functions are in my_ffmpeg_functions.php, then we can create a PHP program called my_testes.php to use these functions:

// estou ignorando as chaves de abrir e fechar do php
include 'my_ffmpeg_functions.php';

transforma_diretorio_filmes("my_movie_dir"); // assumindo 'my_movie_dir' como um valor a ser chamado pelo servidor

Having everything assembled, we can start running on the command line. If I’m not mistaken, to call php CLI, just call the executable php. If it is not available, correct the PATH in order to find the executable php.exe. From there, just rotate the following command on the command line to see if you are behaving as you should:

php my_testes.php
  • I re-organized my real code as proposed in your example, and in fact it seemed to improve a little the performance of the script, but I could not run it by cmd

0

An output is, instead of running the task and waiting, it would run the task in the background and the script go checking from time to time if the process is over.

For this, you have the so-called Cron Jobs in Unix and the Scheduled Windows Tasks. They are commands or scripts that run from time to time.

My suggestion is, in the call of the PHP script, write the paths of the files to be processed in a BD, or even move the videos to a specific folder, and the script (.bat in windows or .sh in Unix) is from time to time being called and looking at that folder, and if you have any files, convert to an output folder and delete the original, or move to another processed folder.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.