GeneratePreviewVideo.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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. $format = new FFMpeg\Format\Video\X264('libfdk_aac');
  76. $video->save($format, $outputPath);
  77. return $outputPath;
  78. }
  79. /*ssssssss
  80. * 把旧数据导入新的预览表
  81. */
  82. function importVideo()
  83. {
  84. try {
  85. // 分批处理数据,避免内存溢出
  86. DB::table('site_album')
  87. ->where('video', '<>', '[]') // 过滤非空 video 字段
  88. ->orderBy('id') // 按主键排序确保顺序
  89. ->chunkById(10000, function ($albums) { // 每次处理 100 条
  90. $insertData = [];
  91. foreach ($albums as $album) {
  92. // 跳过无效 JSON 数据
  93. $videos = json_decode($album->video, true);
  94. if (json_last_error() !== JSON_ERROR_NONE || !is_array($videos)) {
  95. Log::warning("Invalid JSON in album ID: {$album->id}");
  96. continue;
  97. }
  98. foreach ($videos as $video) {
  99. // 校验必要字段存在性
  100. if (empty($video['video_src']) || empty($video['cover'])) {
  101. Log::warning("Missing video_src or cover in album ID: {$album->id}");
  102. continue;
  103. }
  104. // 处理 URL 长度限制
  105. $videoUrl = substr($video['video_src'], 0, 255);
  106. // 构建插入数据
  107. $insertData[] = [
  108. 'video_url' => $videoUrl,
  109. 'preview_url' => '',
  110. 'status' => 0,
  111. 'created_at' => Carbon::now(),
  112. 'updated_at' => Carbon::now(),
  113. ];
  114. }
  115. }
  116. // 插入剩余数据
  117. if (!empty($insertData)) {
  118. DB::table('site_preview_video')->insert($insertData);
  119. }
  120. });
  121. return true;
  122. } catch (\Exception $e) {
  123. Log::error("Video import failed: " . $e->getMessage());
  124. return false;
  125. }
  126. }
  127. }