节目建设页 OCR 侧栏点击填入

This commit is contained in:
2026-07-30 03:38:05 +08:00
parent ec88e6a806
commit 8914a2a609
7 changed files with 407 additions and 11 deletions
+39
View File
@@ -2,6 +2,8 @@
namespace App\Util;
use App\Models\Programs;
use App\Models\ProgramVideos;
use App\Models\VideoOcrRecords;
use App\Models\VideoParts;
use Carbon\Carbon;
@@ -198,6 +200,43 @@ class VideoOcrUtil
];
}
/**
* 建设页 OCR 面板所需的片段元数据(轻量;帧级重数据由前端按返回的 CDN URL 直接拉取)。
* 每个 pivot:id/label/bvid/起止分P与秒/urls(片段范围内有 OCR 的分P CDN 全量 JSON URL)。
* 起止时间未填时对应 sec null(前端不做该侧 in_range 裁剪)。
*/
public static function panel_pivots(Programs $program): array
{
$pivots = $program->video_pivots;
if ($pivots->isEmpty()) {
return [];
}
$bvids = $pivots->pluck("video_bvid")->unique()->all();
$ocrParts = VideoOcrRecords::query()->whereIn("video_bvid", $bvids)
->select("video_bvid", "part_num")->distinct()->get()
->groupBy("video_bvid")->map(fn($rows) => $rows->pluck("part_num")->map(fn($n) => (int)$n)->all())->all();
return $pivots->map(function (ProgramVideos $pivot) use ($ocrParts) {
$startPart = (int)$pivot->start_part;
$stopPart = (int)$pivot->stop_part;
$urls = [];
foreach (($ocrParts[$pivot->video_bvid] ?? []) as $partNum) {
if ($partNum >= $startPart && $partNum <= $stopPart) {
$urls[$partNum] = Storage::url(static::cdn_path($pivot->video_bvid, $partNum));
}
}
return [
"id" => $pivot->id,
"label" => "{$pivot->video_bvid} P{$pivot->start_part} {$pivot->start_time} → P{$pivot->stop_part} {$pivot->stop_time}",
"bvid" => $pivot->video_bvid,
"start_part" => $startPart,
"start_sec" => $pivot->start_sec === "" ? null : $pivot->start_sec,
"stop_part" => $stopPart,
"stop_sec" => $pivot->stop_sec === "" ? null : $pivot->stop_sec,
"urls" => $urls,
];
})->values()->all();
}
private static function time_to_seconds($time): ?float
{
if (is_numeric($time)) {