How do I prevent my site from crashing when running a "heavy" script?

1

I have a script that traverses a directory looking for video files in it and then I use shell_exec with ffmpeg to convert it, the problem is that my site is falling during script execution, after starting even on the server, the site crashes and can not access until I shut down the script, I'm using Wamp installed on a Windows Server 2012.

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

This is my short 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);
}
    
asked by anonymous 08.04.2017 / 01:38

2 answers

1

The first point I see is trying to make your code more testable, separating it into smaller units to see how each one behaves, how much it needs, etc.

I see here that you iterate over a directory, decide if it is a file to be treated and, if this file is desirable, check if you need% additional%, creating a folder if it does not exist. I do not know what query does, but

From here, I come to the conclusion that you need a list of functions that can make your life easier 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's the same code you've posted, but more sliced into smaller, more palatable pieces, each one at a level of abstraction more appropriate than all together. If these functions are in ffmpeg ' -i '.$input.' -hide_banner , then we can create a PHP program called my_ffmpeg_functions.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 set up, we can start running on the command line. If I'm not mistaken, to call the php CLI, just call the executable my_testes.php . If it is not available, correct php to find the PATH executable. Then, just run the following command on the command line to see if you are behaving as you should:

php my_testes.php
    
08.04.2017 / 04:05
0

An exit is, instead of running the task and waiting, it would run the task in the background and the script will check from time to time if the process is over.

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

My suggestion is, in the PHP script call, to write the paths of the files to be processed in a DB, or even move the videos to a specific folder, and the script (.bat on windows or .sh on unix) is from time to time being called and looking at this folder, and if it has any files, it converts to an output folder and deletes the original, or moves to another processed folder.

    
08.04.2017 / 05:14