5
votes

php vidéo upload et ffmpeg ne crée pas de vignette

J'essaie de créer une fonction de téléchargement de vidéo pour mon projet. Mais j'ai un problème avec la section ffmpeg . ffmpeg est déjà installé sur mon serveur. Mais je ne peux pas obtenir de vignette. J'ai essayé de créer une vignette en utilisant le code suivant:

 $local = 'https://website.com/uploads/video/'.$GetVideoName.'.'.$video_ext;
 $localTumb = 'https://website.com/uploads/video/'.$GetVideoName.'.png';
 echo shell_exec("/usr/bin/ffmpeg -i $local -deinterlace -an -ss 1 -t 00:00:05 -r 1 -y -vcodec mjpeg -f mjpeg $localTumb 2>&1");    

Mais je ge ceci lorsque j'utilise var_dump (); pour var_dump ($ videoa); et var_dump($videob);

string (74) " https://mywebsite.com/uploads/video/ey1kXNew_video. flv : Erreur d'entrée / sortie "string (0)" "

Aussi si j'utilise le shell_exec comme ceci:

echo exec("/usr/bin/ffmpeg -i $videoUrlp.flv -ar 22050 -ab 32 -f flv -s 780x400 $videoUrlp.$video_ext");
echo exec("/usr/bin/ffmpeg -i $videoUrlp.$video_ext -deinterlace -an -ss 1 -t 00:00:05 -r 1 -y -vcodec mjpeg -f mjpeg $videoUrlp.png 2>&1");

et le var_dumps () me donnant NULL NULL.

S'il vous plaît, aidez-moi là où je me trompe.

Et voici mon code de téléchargement vidéo complet:

echo exec("/usr/bin/ffmpeg -i $videoUrlp.flv -ar 22050 -ab 32 -f flv -s 780x400 $videoUrlp.$video_ext");
echo exec("/usr/bin/ffmpeg -i $videoUrlp.$video_ext -deinterlace -an -ss 1 -t 00:00:05 -r 1 -y -vcodec mjpeg -f mjpeg $videoUrlp.png 2>&1");

J'ai testé aussi comme ceci:

$valid_formats = array("mp4","MP4","flv");
            if(isset($_POST) and $_SERVER['REQUEST_METHOD'] == "POST") {
               $name = $_FILES['uploading']['name'];
               $size = $_FILES['uploading']['size'];
               if(strlen($name)) {
                   $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION)); 
                   $name = alphaID(microtime(true) * 10000).'_video';
                   if(in_array($ext,$valid_formats)) {
                   if($size<(50024*50024)) {
                      $GetVideoName = $name;
                      $video_ext=$ext;
                       $tmp = $_FILES['uploading']['tmp_name'];
                       if(move_uploaded_file($tmp, $videoPath.$GetVideoName.'.'.$video_ext)) {
                           $videoUrlp = $base_url.'uploads/video/'.$GetVideoName;
                           $videoa = exec("/usr/bin/ffmpeg  -i $videoUrlp.flv -f flv -s 650x390 $videoUrlp.mp4 2>&1");
                           $videob = exec("/usr/bin/ffmpeg  -i $videoUrlp.mp4 -vcodec png -ss 00:00:5 -s 650x390 -vframes 1 -an -f rawvideo $videoUrlp.png");
                           echo var_dump($videoa);
                           echo var_dump($videob);

                        } else {
                            echo "Fail upload folder with read access.";
                        }
                     } else
                        echo "Image file size max 1 MB";                    
                     } else
                        echo "invalidvieo"; 
                 } else
                    echo "Please select image..!";
                 exit;
              }

et je vois l'écho suivant

vidéo: 71 ko audio: 0 ko sous-titre: 0 ko autres flux: 0 ko en-têtes globaux: 0 ko de frais généraux de multiplexage: 0,000000%

et un autre essai alors je reçois cette note: https://mywebsite.com/uploads/video/1547892356_video.flv : Connexion refusée

$videoa = shell_exec("/usr/bin/ffmpeg  -i $videoUrlp.flv -f flv -s 650x390 $videoUrlp.mp4");
$videob = shell_exec("/usr/bin/ffmpeg  -i $videoUrlp.mp4 -vcodec png -ss 00:00:5 -s 650x390 -vframes 1 -an -f rawvideo $videoUrlp.png");

Voici la dernière sortie shell_exec:

$videoa = exec("/usr/bin/ffmpeg  -i $videoUrlp.flv -f flv -s 650x390 $videoUrlp.mp4 2>&1");
$videob = exec("/usr/bin/ffmpeg  -i $videoUrlp.mp4 -vcodec png -ss 00:00:5 -s 650x390 -vframes 1 -an -f rawvideo $videoUrlp.png");

ffmpeg version 2.8.15 Copyright (c) 2000-2018 les développeurs FFmpeg construits avec gcc 4.8.5 (GCC) 20150623 (Red Hat 4.8.5-36) configuration: --prefix = / usr --bindir = / usr / bin
--datadir = / usr / share / ffmpeg --incdir = / usr / include / ffmpeg --libdir = / usr / lib64 --mandir = / usr / share / man --arch = x86_64 --optflags = '- O2 -g -pipe -Wall -Wp, -D_FORTIFY_SOURCE = 2 -fexceptions -fstack-protector-strong --param = ssp-buffer-size = 4 -grecord-gcc-switches -m64 -mtune = generic '--extra-ldflags = '- Wl, -z, relro' --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libvo-amrwbenc --enable-version3 --enable-bzlib --disable-crystalhd --enable- gnutls --enable-ladspa --enable-libass --enable-libcdio --enable-libdc1394 --enable-libfdk-aac --enable-nonfree --disable-indev = jack --enable-libfreetype --enable-libgsm --enable-libmp3lame --enable-openal --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-libschroedinger --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libvorbis --enable-libv4l2 --enable-libx264 --enable-libx265 --enable-libxvid --enable-x11grab --enable-avfilter --enable-avresample --enable-postproc --enable-pthreads --disable-static--enable-shared --enable-gpl --disable-debug --disable-stripping --shlibdir = / usr / lib64 --enable-runtime-cpudetect libavutil 54. 31.100 / 54. 31.100 libavcodec 56. 60.100 / 56. 60.100 libavformat 56. 40.101 / 56. 40.101 libavdevice 56. 4.100 / 56. 4.100 libavfilter 5. 40.101 / 5. 40.101 libavresample 2. 1. 0 / 2. 1. 0 libswscale 3. 1.101 / 3. 1.101 libswresample 1. 2.101 / 1. 2.101 libpostproc 53. 3.100 / 53. 3.100 Entrée n ° 0, mov, mp4, m4a, 3gp, 3g2, mj2, depuis ' https : //website.com/uploads/video/e0J6HwtK_video.mp4 ': Métadonnées: major_brand: mp42 minor_version: 0 compatible_brands: isommp42 creation_time: 2018-01-01 12:09:49 Durée: 00: 00: 41.49, début: 0,000000, débit binaire: 230 kb / s Flux n ° 0: 0 (und): Vidéo: h264 (Contrainte de base) (avc1 / 0x31637661), yuv420p, 240x360 [SAR 1: 1 DAR 2: 3], 158 kb / s, 9,73 ips, 9,73 tbr, 19462 tbn, 19,46 tbc (par défaut) Métadonnées: nom_handler: VideoHandler Stream # 0: 1 (und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 71 kb / s (par défaut) Métadonnées: creation_time: 2018-01-01 12:09:49 nom_handler: Fichier IsoMedia Produit par Google, 5-11-2011 [swscaler @ 0xc8c580] pixel obsolète format utilisé, assurez-vous que vous avez correctement défini la plage Sortie # 0, mjpeg, à ' https://website.com/uploads/video/e0J6HwtK_video.png ' : Métadonnées: major_brand: mp42 minor_version: 0 compatible_brands: isommp42 encodeur: Lavf56.40.101 Stream # 0: 0 (und): Vidéo: mjpeg, yuvj420p (pc), 240x360 [SAR 1: 1 DAR 2: 3], q = 2-31, 200 kb / s, 1 ips, 1 To, 1 To (par défaut) Métadonnées: nom_handler: encodeur VideoHandler: Lavc56.60.100 mjpeg Mappage de flux: Stream # 0: 0 -> # 0: 0 (h264 (natif) -> mjpeg (natif)) Appuyez sur [q] pour arrêter, [?] pour la trame d'aide = 5 fps = 0,0 q = 1,6 Lsize = 100kB time = 00: 00: 05.00 bitrate = 163.9kbits / s dup = 0 drop = 32 vidéo: 100 ko audio: 0 ko sous-titre: 0 ko autres flux: 0 ko global headers: 0 Ko de frais généraux de multiplexage: 0,000000%


15 commentaires

Et si vous exécutez la commande FFMPEG dans le shell? De plus, pour créer un exemple MCV , vous pouvez d'abord essayer de l'exécuter dans un nouveau PHP: var_dump (exec (' / usr / bin / ffmpeg -version '));


@Raptor L'impression comme ceci: string (38) "libpostproc 53. 3.100 / 53. 3.100"


@Raptor shell_exec donnant mie NULL NULL dans var_dump ();


Si l'exemple d'une ligne est capable de donner une sortie valide (comme vous venez de le tester), le problème réside uniquement dans la commande FFMPEG elle-même. Essayez de l'exécuter directement dans le shell, à la place via PHP.


@Raptor Que voulez-vous dire avec directement dans le shell ?


Exécutez sur votre ordinateur / serveur. Utilisez votre console Terminal / Shell sur votre machine Linux. Est-ce un Mac ou Linux?


@Raptor J'essaye le serveur en ligne. C'est Linux mais je ne sais pas comment utiliser le terminal dans le serveur en ligne.


@Azzo Votre hôte a probablement des instructions sur la façon d'utiliser ssh pour se connecter à votre serveur. Sans essayer ffmpeg directement et sans script dans une interface de ligne de commande, nous ne pouvons que deviner et ne pas apporter de réponses réelles.


@llogan Voici l'impression de ssh: prnt.sc/m74ztc pouvez-vous le vérifier pour moi s'il vous plaît. peut-être que cela aidera


Depuis votre dernière mise à jour d'informations, votre commande FFMPEG est en cours d'exécution. Notez que exec () ne renvoie que la dernière ligne du résultat. Notez également que votre deuxième commande contient 2> & 1 à la fin, ce qui redirige la sortie ailleurs. Si j'étais vous, je redirigerai la sortie vers un fichier journal. Et vous analysez le fichier journal quelque temps plus tard.


Pour ce faire, vous pouvez modifier votre deuxième commande en: / usr / bin / ffmpeg -i $ videoUrlp. $ Video_ext -deinterlace -an -ss 1 -t 00:00:05 -r 1 -y -vcodec mjpeg -f mjpeg $ videoUrlp.png> /chemin/to/your/log/file.log 2> & 1


J'ai déjà fait quelque chose de similaire, mais j'utilisais cronjob à la place. Le cronjob surveille un dossier pour un nouveau fichier et le gère une fois trouvé. L'ensemble du processus est journalisé et automatisé, c'est-à-dire qu'il n'est pas nécessaire d'exécuter PHP pour exécuter la commande, ce qui évite des problèmes tels que le délai d'expiration du navigateur, le délai d'expiration du réseau, les tâches à moitié terminées, etc.


Apparemment, vous essayez de sortir sur https://mywebsite.com/uploads/video/ . Comment c'est censé fonctionner? Vous ne pouvez pas sortir arbitrairement vers un serveur sans aucune information d'identification. Si le serveur qui exécute ffmpeg est le même que celui hébergeant le site que vous souhaitez générer, utilisez des chemins locaux, et non via le protocole HTTPS.


@llogan Pouvez-vous l'expliquer via le code s'il vous plaît?


@Azzo Non, car je ne sais pas si le même serveur est utilisé à la fois pour héberger le site et exécuter ffmpeg.


4 Réponses :


7
votes

Si vous utilisez https, votre ffmpeg doit être configuré avec le support ssl ( ffmpeg over https échoue < / a>).


0 commentaires

3
votes

utilisez ce code: » // Le chemin du pouce doit être ajouté dans le code ci-dessous // test pour le pouce

      $dir_img='uploads/';
      $mediapath='123.jpg';

      $file_thumb=create_movie_thumb($dir_img.$mediapath,$mediapath,$mediaid);

        $name_file=explode(".",$mediapath);
        $imgname="thumb_".$name_file[0].".jpg";     



        /*
          Function to create video thumbnail using ffmpeg
        */
        function create_movie_thumb($src_file,$mediapath,$mediaid)
        {
            global $CONFIG, $ERROR;

            $CONFIG['ffmpeg_path'] = '/usr/local/bin/'; // Change the path according to your server.
            $dir_img='uploads/';
            $CONFIG['fullpath'] = $dir_img."thumbs/";

            $src_file = $src_file;
            $name_file=explode(".",$mediapath);
            $imgname="thumb_".$name_file[0].".jpg";
            $dest_file = $CONFIG['fullpath'].$imgname;

            if (preg_match("#[A-Z]:|\\\\#Ai", __FILE__)) {
                // get the basedir, remove '/include'
                $cur_dir = substr(dirname(__FILE__), 0, -8);
                $src_file = '"' . $cur_dir . '\\' . strtr($src_file, '/', '\\') . '"';
                $ff_dest_file = '"' . $cur_dir . '\\' . strtr($dest_file, '/', '\\') . '"';
            } else {
                $src_file = escapeshellarg($src_file);
                $ff_dest_file = escapeshellarg($dest_file);
            }

            $output = array();

            if (eregi("win",$_ENV['OS'])) {
                // Command to create video thumb
                $cmd = "\"".str_replace("\\","/", $CONFIG['ffmpeg_path'])."ffmpeg\" -i ".str_replace("\\","/" ,$src_file )." -an -ss 00:00:05 -r 1 -vframes 1 -y ".str_replace("\\","/" ,$ff_dest_file);
                exec ("\"$cmd\"", $output, $retval);

            } else {
                // Command to create video thumb
                $cmd = "{$CONFIG['ffmpeg_path']}ffmpeg -i $src_file -an -ss 00:00:05 -r 1 -vframes 1 -y $ff_dest_file";
                exec ($cmd, $output, $retval);

            }


            if ($retval) {
                $ERROR = "Error executing FFmpeg - Return value: $retval";
                if ($CONFIG['debug_mode']) {
                    // Re-execute the command with the backtick operator in order to get all outputs
                    // will not work if safe mode is enabled
                    $output = `$cmd 2>&1`;
                    $ERROR .= "<br /><br /><div align=\"left\">Cmd line : <br /><span style=\"font-size:120%\">" . nl2br(htmlspecialchars($cmd)) . "</span></div>";
                    $ERROR .= "<br /><br /><div align=\"left\">The ffmpeg program said:<br /><span style=\"font-size:120%\">";
                    $ERROR .= nl2br(htmlspecialchars($output));
                    $ERROR .= "</span></div>";
                }
                @unlink($dest_file);
                return false;
            }

            $return = $dest_file;
            //@chmod($return, octdec($CONFIG['default_file_mode'])); //silence the output in case chmod is disabled
            return $return;
        }`


0 commentaires

5
votes

les arguments doivent être échappés, vous ne pouvez pas simplement y vider les variables en tant qu'arguments, les URL contiennent des éléments comme & qui ont une signification particulière dans les shells .. par exemple ce

exec ("/ usr / bin / ffmpeg -i $ videoUrlp.flv -f flv -s 650x390 $ videoUrlp.mp4 2> & 1");

aurait dû être ceci:

exec ("/ usr / bin / ffmpeg -i" .escapeshellarg ($ videoUrlp.flv). "-f flv -s 650x390" .escapeshellarg ($ videoUrlp.mp4). "2> & 1"); p>

mais ..

s'il vous plaît, n'importe qui peut m'aider?

voici 2 fonctions pour obtenir la vignette, getThumbPng2 () téléchargera d'abord la vidéo entière avec curl, l'enregistrera dans un fichier temporaire, puis extraira l'url avec ffmpeg (c'est plus sûr si ffmpeg n'est pas ' t construit avec http / https / quel que soit le support, ou si ffmpeg est bloqué par un pare-feu ou autre, mais l'inconvénient est qu'il est potentiellement beaucoup plus lent)

et la première fonction récupère la vignette de ffmpeg sans récupérer le la vidéo en premier (ce qui est potentiellement beaucoup plus rapide car ffmpeg lira simplement les parties requises au lieu de télécharger la vidéo entière, mais peut ne pas fonctionner pour les raisons expliquées ci-dessus)

<?php
if(getThumbPng("http://files.4x4norway.no/2018/vik2.webm",$imageBinary,$stderr)){
    echo "got a thumbnail! (the png binary data is in the \$imageBinary variable.)";
}else{
    var_dump($imageBinary);
    echo "failed to create thumbnail! error: {$stderr}";
}

Exemple d'utilisation:

function getThumbPng2(string $uri, string &$imageBinary=NULL, string &$stderr=NULL):bool{
    $ch=curl_init($uri);
    if(!$ch){
        $imageBinary=$stderr="curl_init() failed";
        return false;
    }
    $tmph=tmpfile();
    curl_setopt_array($ch,array(
        CURLOPT_SSL_VERIFYPEER=>false,
        CURLOPT_SSL_VERIFYHOST=>false,
        CURLOPT_FILE=>$tmph
    ));
    if(!curl_exec($ch)){
        $imageBinary=$stderr="curl error: ".curl_errno($ch).": ".curl_error($ch);
        curl_close($ch);
        fclose($tmph);
        return false;
    }
    curl_close($ch);
    $ret=getThumbPng(stream_get_meta_data($tmph)['uri'],$imageBinary,$stderr);
    fclose($tmph);
    return $ret;
}
function getThumbPng(string $uri,string &$imageBinary=NULL, string &$stderr=NULL):bool{
    $imageBinary="";
    $stderr="";
    $descriptorspec = array(
        0 => array("pipe", "rb"),  // stdin
        1 => array("pipe", "wb"),  // stdout
        2 => array("pipe","wb") // stderr 
    );
    $cmd="ffmpeg -i ".escapeshellarg($uri)." -ss 00:00:3 -s 650x390 -vframes 1 -c:v png -f image2pipe -";
    // var_dump($cmd);
    $proc = proc_open($cmd, $descriptorspec, $pipes);
    if(!$proc){
        $stderr="failed to start ffmpeg, proc_open(\"ffmpeg\",...) failed. (why? don't know, and PHP has no way of telling us either, afaik.)";
        return false;
    }
    fclose($pipes[0]);// by default stdin is *inherited*, which is not what we want,
    // so to avoid the default behaviour, we explicitly create a stdin pipe and close it.
    $fetch=function()use(&$pipes,&$imageBinary,&$stderr){
        $tmp=stream_get_contents($pipes[1]);
        if(is_string($tmp)){
            $imageBinary.=$tmp;
        }
        $tmp=stream_get_contents($pipes[2]);
        if(is_string($tmp)){
            $stderr.=$tmp;
        }   
    };
    while(($status=proc_get_status($proc))['running']){
        usleep(10*1000);
        $fetch();
    }
    $fetch();
    fclose($pipes[1]);
    fclose($pipes[2]);
    $ret=$status['exitcode'];
    proc_close($proc);
    //var_dump($ret);
    return ($ret===0);
}


0 commentaires

1
votes

Je pense que vous pouvez vérifier le fichier installé ffmpeg sur votre serveur.

$cmd = shell_exec("$ffmpeg -i $videoUrlp.mp4 -ss 00:00:02.000 -vframes 1 $videoUrlp.png");

Ensuite, essayez ceci:

$ffmpeg = trim(shell_exec('whereis ffmpeg')); // This will show you which path FFMPEG 

if (empty($ffmpeg))
{
    die('ffmpeg not available');
}else{
    echo $ffmpeg;
}


0 commentaires