Procházet zdrojové kódy

新增提高视频分辨率的公共方法

lh před 2 dny
rodič
revize
567eda8e72
1 změnil soubory, kde provedl 122 přidání a 0 odebrání
  1. 122 0
      app/Libs/Helpers.php

+ 122 - 0
app/Libs/Helpers.php

@@ -4429,3 +4429,125 @@ function mapErrorMessage($errorMessage)
     // 默认返回
     return '未知异常,请重试';
 }
+
+/**
+ * 将480p视频升级到720p
+ * 使用FFmpeg保持宽高比和画质尽量不丢失
+ * 
+ * @param string $videoUrl 视频URL地址
+ * @param string $prefix 上传文件夹前缀(如:'videos')
+ * @return string 返回升级后的视频URL,失败返回原视频URL
+ */
+function upgrade480pTo720p($videoUrl, $prefix = 'videos')
+{
+    if (env('APP_ENV') == 'local') return $videoUrl;
+
+    try {
+        // 创建临时目录
+        $tempDir = storage_path('app/temp/videos');
+        if (!is_dir($tempDir)) {
+            mkdir($tempDir, 0775, true);
+            chmod($tempDir, 0775);
+        }
+
+        // 生成唯一文件名
+        $uniqueId = uniqid('video_upgrade_') . bin2hex(random_bytes(4));
+        $videoExt = getVideoExtFromUrl($videoUrl);
+        $inputFile = $tempDir . '/' . $uniqueId . '_input' . $videoExt;
+        $outputFile = $tempDir . '/' . $uniqueId . '_output.mp4';
+
+        // 下载视频到本地
+        dLog('video_upgrade')->info('开始下载视频进行升级', ['url' => $videoUrl]);
+        $client = new \GuzzleHttp\Client(['timeout' => 300]);
+        $response = $client->get($videoUrl);
+        
+        $fileContent = $response->getBody()->getContents();
+        if (file_put_contents($inputFile, $fileContent) === false) {
+            dLog('video_upgrade')->error('视频文件写入失败', [
+                'url' => $videoUrl,
+                'file' => $inputFile
+            ]);
+            return $videoUrl;
+        }
+        
+        chmod($inputFile, 0664);
+
+        if (!file_exists($inputFile)) {
+            dLog('video_upgrade')->error('视频下载失败', ['url' => $videoUrl]);
+            return $videoUrl;
+        }
+
+        $inputFileSize = filesize($inputFile);
+        dLog('video_upgrade')->info('视频下载成功,准备升级到720p', [
+            'url' => $videoUrl,
+            'size' => $inputFileSize,
+            'size_mb' => round($inputFileSize / 1024 / 1024, 2) . 'MB'
+        ]);
+
+        // 使用FFmpeg将视频升级到720p
+        // -vf "scale=-2:720": 保持宽高比,高度设置为720,宽度自动计算(-2确保是偶数)
+        // -c:v libx264: 使用H.264编码器
+        // -preset slow: 使用较慢的编码速度以保持更好的画质
+        // -crf 18: 恒定质量模式,18表示高质量(0-51,数值越小画质越好)
+        // -c:a copy: 音频直接复制,不重新编码
+        // -movflags +faststart: 优化网络播放
+        $ffmpegPath = env('FFMPEG_PATH', 'ffmpeg');
+        $ffmpegCmd = "$ffmpegPath -i \"$inputFile\" -vf \"scale=-2:720\" -c:v libx264 -preset slow -crf 18 -c:a copy -movflags +faststart -y \"$outputFile\" 2>&1";
+        
+        dLog('video_upgrade')->info('开始升级视频到720p', ['command' => $ffmpegCmd]);
+        $output = shell_exec($ffmpegCmd);
+
+        if (!file_exists($outputFile)) {
+            dLog('video_upgrade')->error('视频升级失败', [
+                'input' => $inputFile,
+                'output' => $output
+            ]);
+            @unlink($inputFile);
+            return $videoUrl;
+        }
+        
+        chmod($outputFile, 0664);
+
+        $outputFileSize = filesize($outputFile);
+        $sizeRatio = round($outputFileSize / $inputFileSize, 2);
+
+        dLog('video_upgrade')->info('视频升级成功', [
+            'input_size' => round($inputFileSize / 1024 / 1024, 2) . 'MB',
+            'output_size' => round($outputFileSize / 1024 / 1024, 2) . 'MB',
+            'size_ratio' => $sizeRatio
+        ]);
+
+        // 上传到TOS - 使用普通的文件名,不暴露是升级后的视频
+        $video_name = 'ai_generation_' . time() . '_' . uniqid() . '.mp4';
+        $uploadedUrl = uploadStreamByTos($prefix, file_get_contents($outputFile), $video_name);
+
+        // 清理临时文件
+        @unlink($inputFile);
+        @unlink($outputFile);
+
+        if (!$uploadedUrl) {
+            dLog('video_upgrade')->error('升级后的视频上传失败');
+            return $videoUrl;
+        }
+
+        dLog('video_upgrade')->info('升级后的视频上传成功', ['url' => $uploadedUrl]);
+        return $uploadedUrl;
+
+    } catch (\Exception $e) {
+        dLog('video_upgrade')->error('视频升级过程出错', [
+            'url' => $videoUrl,
+            'error' => $e->getMessage()
+        ]);
+        
+        // 清理可能存在的临时文件
+        if (isset($inputFile) && file_exists($inputFile)) {
+            @unlink($inputFile);
+        }
+        if (isset($outputFile) && file_exists($outputFile)) {
+            @unlink($outputFile);
+        }
+        
+        // 出错时返回原视频URL
+        return $videoUrl;
+    }
+}