| @ -0,0 +1,223 @@ | |||||
| <?php | |||||
| namespace App\Services; | |||||
| use App\Utils\FileUtils; | |||||
| use Illuminate\Support\Facades\Log; | |||||
| use Illuminate\Support\Facades\Redis; | |||||
| use Mhor\MediaInfo\MediaInfo; | |||||
| class FfmpegService | |||||
| { | |||||
| private $mediainfo; | |||||
| public function __construct() | |||||
| { | |||||
| $this->mediainfo = new MediaInfo(); | |||||
| $this->mediainfo->setConfig('use_oldxml_mediainfo_output_format', true); | |||||
| } | |||||
| public function handleVideos($dir = "/Users/shixuesen/Documents/tmp/柚木/2017/泡泡条纹袜/") | |||||
| { | |||||
| $files = scandir($dir); | |||||
| foreach ($files as $file) { | |||||
| if ($file == "." || $file == "..") { | |||||
| continue; | |||||
| } | |||||
| $subDir = implode("/", [$dir, $file]); | |||||
| $isDir = is_dir($subDir); | |||||
| if ($isDir) { | |||||
| $subFiles = scandir($subDir); | |||||
| foreach ($subFiles as $subFile) { | |||||
| $subPathFile = implode("/", [$subDir, $subFile]); | |||||
| if (is_dir($subPathFile) || $subFile == ".DS_Store") { | |||||
| continue; | |||||
| } | |||||
| $mime = mime_content_type($subPathFile); | |||||
| // dump("file type", [$mime, $subPathFile]); | |||||
| // continue; | |||||
| if (strstr($mime, "video/")) { | |||||
| if (is_file($subPathFile)) { | |||||
| $fileInfo = pathinfo($subPathFile); | |||||
| dump("fileInfo", $fileInfo); | |||||
| if (ends_with($fileInfo["filename"], "-1")) { | |||||
| continue; | |||||
| } | |||||
| if (is_file($fileInfo["dirname"] . '/' .$fileInfo["filename"] . '-1'. '.' . $fileInfo["extension"])) { | |||||
| unlink($subPathFile); | |||||
| continue; | |||||
| } | |||||
| $targetFile = $fileInfo["dirname"] . '/' .$fileInfo["filename"] . '-1'. '.' . $fileInfo["extension"]; | |||||
| dump("targetFile", [$targetFile]); | |||||
| // $result = shell_exec("handBrakeCli -Z 'Very Fast 720p30' -i '". $subPathFile ."' -o '". $targetFile . " && echo 'success'"); | |||||
| $result = shell_exec("handBrakeCli -Z 'Very Fast 720p30' -i '". $subPathFile ."' -o '". $targetFile . "'"); | |||||
| dump($result); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| print_r($files); | |||||
| } | |||||
| // public function processDir($baseDir = "/Volumes/WD/Video/HuaVid/") | |||||
| public function processDir($baseDir = "/Volumes/Backup/HuaVid/大忽悠") | |||||
| { | |||||
| $files = scandir($baseDir); | |||||
| foreach ($files as $file) { | |||||
| if ($file == "." || $file == ".." || $file == ".DS_Store") { | |||||
| continue; | |||||
| } | |||||
| $subDir = implode("/", [$baseDir, $file]); | |||||
| $isDir = is_dir($subDir); | |||||
| if ($isDir) { | |||||
| $this->processDir($subDir); | |||||
| } else { | |||||
| $this->processVideo($subDir); | |||||
| } | |||||
| } | |||||
| } | |||||
| public function processVideo($pathFile) | |||||
| { | |||||
| $mime = mime_content_type($pathFile); | |||||
| $mediaInfo = new MediaInfo(); | |||||
| $mediaInfo->setConfig('use_oldxml_mediainfo_output_format', true); | |||||
| if (strstr($mime, "video/") || strstr($mime, "application/octet-stream")) { | |||||
| if (is_file($pathFile)) { | |||||
| if (!$this->checkFileSize($pathFile)) { | |||||
| return; | |||||
| } | |||||
| $fileInfo = pathinfo($pathFile); | |||||
| if (ends_with($fileInfo["filename"], "-x265")) { | |||||
| return; | |||||
| } | |||||
| if (Redis::sismember("unneed", $fileInfo["filename"])) { | |||||
| return; | |||||
| } | |||||
| $targetFile = $fileInfo["dirname"] . '/' .$fileInfo["filename"] . '-x265'. '.' . $fileInfo["extension"]; | |||||
| if (is_file($targetFile)) { | |||||
| unlink($pathFile); | |||||
| rename($targetFile, $pathFile); | |||||
| return; | |||||
| } | |||||
| dump("targetFile", [$targetFile]); | |||||
| $result = shell_exec("ffmpeg -i '". $pathFile ."' -c:v libx265 -vtag hvc1 '" . $targetFile . "' && echo 'ok'"); | |||||
| echo $result; | |||||
| if ($result == "ok") { | |||||
| echo "compress work done remove the file \n"; | |||||
| $oldFileSize = filesize($pathFile); | |||||
| $newFileSize = filesize($targetFile); | |||||
| if ($newFileSize >= $oldFileSize) { | |||||
| Redis::sadd("unneed", $fileInfo["filename"]); | |||||
| echo "old file size is smaller than new one, old is " . file_size($oldFileSize) . " and new is " . file_size($newFileSize) . ", now remove new one"; | |||||
| unlink($targetFile); | |||||
| } else { | |||||
| echo "new file size is smaller than old one, new is " . file_size($newFileSize) . " and old is " . file_size($oldFileSize) . ", now remove old one"; | |||||
| unlink($pathFile); | |||||
| rename($targetFile, $pathFile); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| public function processUnCompleteDir($baseDir = "/Volumes/WD/tmp/探花系列【AI高清2K修复】大合集") | |||||
| // public function processDir($baseDir = "/Volumes/Backup/iPhone nPlayer/") | |||||
| { | |||||
| $files = scandir($baseDir); | |||||
| foreach ($files as $file) { | |||||
| if ($file == "." || $file == "..") { | |||||
| continue; | |||||
| } | |||||
| $subDir = implode("/", [$baseDir, $file]); | |||||
| $isDir = is_dir($subDir); | |||||
| if ($isDir) { | |||||
| $this->processUnCompleteDir($subDir); | |||||
| } else { | |||||
| $this->processUnCompleteVideo($subDir); | |||||
| } | |||||
| } | |||||
| } | |||||
| public function processUnCompleteVideo($pathFile) | |||||
| { | |||||
| //... | |||||
| $mediaInfo = new MediaInfo(); | |||||
| $mediaInfo->setConfig('use_oldxml_mediainfo_output_format', true); | |||||
| $mime = mime_content_type($pathFile); | |||||
| // dump("file type", [$mime, $subPathFile]); | |||||
| // continue; | |||||
| if (strstr($mime, "video/")) { | |||||
| if (is_file($pathFile)) { | |||||
| $fileInfo = pathinfo($pathFile); | |||||
| // dump("fileInfo", $fileInfo); | |||||
| if (ends_with($fileInfo["filename"], "-1")) { | |||||
| return; | |||||
| } | |||||
| if (is_file($fileInfo["dirname"] . '/' .$fileInfo["filename"] . '-1'. '.' . $fileInfo["extension"])) { | |||||
| $mediaInfoContainer1 = $mediaInfo->getInfo($fileInfo["dirname"] . '/' .$fileInfo["filename"] . '-1'. '.' . $fileInfo["extension"]); | |||||
| $millSecond1 = $mediaInfoContainer1->getGeneral()->get("duration")->getMilliseconds(); | |||||
| echo gettype($millSecond1) . "\n"; | |||||
| // ["duration"] . "\n"; | |||||
| $mediaInfoContainer = $mediaInfo->getInfo($pathFile); | |||||
| $millSecond = $mediaInfoContainer->getGeneral()->get("duration")->getMilliseconds(); | |||||
| echo gettype($millSecond) . "\n"; | |||||
| if (abs(intval($millSecond) - intval($millSecond1)) > 100) { | |||||
| echo $pathFile . "\n"; | |||||
| echo abs(intval($millSecond) - intval($millSecond1)) . "\n"; | |||||
| } | |||||
| // unlink($pathFile); | |||||
| return; | |||||
| } | |||||
| // $targetFile = $fileInfo["dirname"] . '/' .$fileInfo["filename"] . '-1'. '.' . $fileInfo["extension"]; | |||||
| // dump("targetFile", [$targetFile]); | |||||
| //// $result = shell_exec("handBrakeCli -Z 'Very Fast 720p30' -i '". $subPathFile ."' -o '". $targetFile . " && echo 'success'"); | |||||
| // $result = shell_exec("handBrakeCli -Z 'Very Fast 720p30' -i '". $pathFile ."' -o '". $targetFile . "'"); | |||||
| // dump($result); | |||||
| } | |||||
| } | |||||
| } | |||||
| public function checkFileDimension($file) : bool | |||||
| { | |||||
| $mediaContainer = $this->mediainfo->getInfo($file); | |||||
| foreach ($mediaContainer->getVideos() as $video) { | |||||
| $height = $video->get('height')->getAbsoluteValue(); | |||||
| $width = $video->get('width')->getAbsoluteValue(); | |||||
| if ($height > $width && $width <= 720) { | |||||
| echo "$file 分辨率小于 720p 跳过\n"; | |||||
| return false; | |||||
| } | |||||
| if ($height <= $width && $height <= 720) { | |||||
| echo "$file 分辨率小于 720p 跳过\n"; | |||||
| return false; | |||||
| } | |||||
| } | |||||
| return true; | |||||
| } | |||||
| public function checkFileSize($file, $size = 1): bool | |||||
| { | |||||
| if (is_file($file) && filesize($file) > 100 * 1024 * 1024) { | |||||
| return true; | |||||
| } | |||||
| $fileSize = FileUtils::humanFilesize(filesize($file)); | |||||
| echo "$file size < 100Mb filesize is $fileSize skip \n"; | |||||
| return false; | |||||
| } | |||||
| } | |||||