You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

261 lines
11 KiB

<?php
namespace App\Services;
use App\Utils\FileUtils;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Mhor\MediaInfo\MediaInfo;
use FFMpeg\FFProbe;
class FfmpegService
{
private $mediainfo;
private $ffprobe;
public function __construct()
{
$this->mediainfo = new MediaInfo();
$this->mediainfo->setConfig('use_oldxml_mediainfo_output_format', true);
$config = array(
'ffmpeg.binarie' => '/usr/local/bin/ffmpeg',
'ffprobe.binaries' => '/usr/local/bin/ffprobe',
'timeout' => 3600,
'ffmpeg.threads' => 12,
);
$this->ffprobe = FFProbe::create($config);
}
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;
}
if ($this->checkFileEncodeType($pathFile)) {
Log::info("$pathFile has already encode by h265 return");
return;
}
if (filemtime($pathFile) > strtotime("2021-07-26 00:00:00")) {
$mtime = date("Y-m-d H:i:s", filemtime($pathFile));
dump("$pathFile modify at $mtime is after 2021-07-26 00:00:00 skip");
return;
} else {
$mtime = date("Y-m-d H:i:s", filemtime($pathFile));
dump("$pathFile modify at $mtime is before 2021-07-19 00:00:00");
}
$fileInfo = pathinfo($pathFile);
if (ends_with($fileInfo["filename"], "-x265")) {
return;
}
if (Redis::sismember("unneed", $fileInfo["filename"])) {
return;
}
if (Redis::get("stopFlag") != null) {
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 -threads 4 -i '". $pathFile ."' -c:v libx265 -vtag hvc1 '" . $targetFile . "' && echo 'ok'");
echo $result;
if (trim($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 {
Redis::sadd("unneed", $fileInfo["filename"]);
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 < 200Mb filesize is $fileSize skip \n";
return false;
}
public function checkFileEncodeType($file): bool
{
$codecName = $this->ffprobe
->streams($file) // extracts streams informations
->videos() // filters video streams
->first() // returns the first video stream
->get('codec_name');
return trim($codecName) == "hevc";
}
}