GeneratePreviewVideo.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. <?php
  2. namespace App\Console\Commands;
  3. use App\Libraries\CommonHelper;
  4. use Illuminate\Console\Command;
  5. use Illuminate\Support\Carbon;
  6. use Illuminate\Support\Facades\DB;
  7. use Illuminate\Support\Facades\Log;
  8. use Dcat\Admin\Traits\HasUploadedFile;
  9. use FFMpeg\FFMpeg;
  10. use FFMpeg\Coordinate\TimeCode;
  11. /*
  12. * 生成预览10秒视频
  13. *
  14. * @author <EMAIL>
  15. * 运行命令:php artisan command:preview-video
  16. */
  17. class GeneratePreviewVideo extends Command
  18. {
  19. use HasUploadedFile;
  20. /**
  21. * The name and signature of the console command.
  22. *
  23. * @var string
  24. */
  25. protected $signature = 'command:preview-video';
  26. /**
  27. * The console command description.
  28. *
  29. * @var string
  30. */
  31. protected $description = '生成预览视频';
  32. public $timeSecond = 5;
  33. /**
  34. * Execute the console command.
  35. *
  36. * @return int
  37. */
  38. public function handle()
  39. {
  40. $disk = $this->disk('oss');
  41. $reslut = DB::table('site_preview_video')
  42. ->where('status', '==', 0) // 过滤非空 video 字段
  43. ->orderBy('id') // 按主键排序确保顺序
  44. ->get();
  45. foreach ($reslut as $item) {
  46. $video_url = $this->ossUrl($item->video_url);
  47. $fileName = basename($video_url);
  48. $fileInfo = pathinfo($fileName);
  49. $previewName = $fileInfo['filename'] . '_preview.' . $fileInfo['extension'];
  50. $previewPath = storage_path('tmp/previews/'.$previewName);
  51. $this->generatePreview($video_url, $previewPath);
  52. dd($previewPath);
  53. exit;
  54. }
  55. //$this->importVideo();
  56. return Command::SUCCESS;
  57. }
  58. private function ossUrl($url)
  59. {
  60. if (strpos($url, 'http:') === 0 || strpos($url, 'https:') === 0) {
  61. return $url;
  62. }
  63. return "https://mietublcom.oss-cn-hongkong.aliyuncs.com".'/'.$url;
  64. }
  65. public function generatePreview($inputUrl, $outputPath) {
  66. $ffmpeg = FFMpeg::create([
  67. 'ffmpeg.binaries' => '/usr/bin/ffmpeg',
  68. 'ffprobe.binaries' => '/usr/bin/ffprobe',
  69. 'timeout' => 300
  70. ]);
  71. $video = $ffmpeg->open($inputUrl);
  72. $video->filters()->clip(TimeCode::fromSeconds(0), TimeCode::fromSeconds($this->timeSecond));
  73. // 输出为H.264编码的MP4
  74. $format = new \FFMpeg\Format\Video\X264('aac');
  75. $video->save($format, $outputPath);
  76. return $outputPath;
  77. }
  78. /*ssssssss
  79. * 把旧数据导入新的预览表
  80. */
  81. function importVideo()
  82. {
  83. try {
  84. // 分批处理数据,避免内存溢出
  85. DB::table('site_album')
  86. ->where('video', '<>', '[]') // 过滤非空 video 字段
  87. ->orderBy('id') // 按主键排序确保顺序
  88. ->chunkById(10000, function ($albums) { // 每次处理 100 条
  89. $insertData = [];
  90. foreach ($albums as $album) {
  91. // 跳过无效 JSON 数据
  92. $videos = json_decode($album->video, true);
  93. if (json_last_error() !== JSON_ERROR_NONE || !is_array($videos)) {
  94. Log::warning("Invalid JSON in album ID: {$album->id}");
  95. continue;
  96. }
  97. foreach ($videos as $video) {
  98. // 校验必要字段存在性
  99. if (empty($video['video_src']) || empty($video['cover'])) {
  100. Log::warning("Missing video_src or cover in album ID: {$album->id}");
  101. continue;
  102. }
  103. // 处理 URL 长度限制
  104. $videoUrl = substr($video['video_src'], 0, 255);
  105. // 构建插入数据
  106. $insertData[] = [
  107. 'video_url' => $videoUrl,
  108. 'preview_url' => '',
  109. 'status' => 0,
  110. 'created_at' => Carbon::now(),
  111. 'updated_at' => Carbon::now(),
  112. ];
  113. }
  114. }
  115. // 插入剩余数据
  116. if (!empty($insertData)) {
  117. DB::table('site_preview_video')->insert($insertData);
  118. }
  119. });
  120. return true;
  121. } catch (\Exception $e) {
  122. Log::error("Video import failed: " . $e->getMessage());
  123. return false;
  124. }
  125. }
  126. }