2026-05-25 14:32:52 +08:00

136 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 视频转码统计 API(管理员)
*
* 提供转码任务的统计信息
*/
import { NextRequest, NextResponse } from 'next/server'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'
import { prisma } from '@/lib/prisma'
import { transcodeQueue } from '@/lib/video-transcode-queue'
import { isCurrentAdmin } from '@/lib/admin-permissions'
export const dynamic = 'force-dynamic'
/**
* GET /api/admin/video-transcode-stats
* 获取转码统计信息
*/
export async function GET(req: NextRequest) {
try {
const session = await getServerSession(authOptions)
if (!session) {
return NextResponse.json(
{ error: '未登录' },
{ status: 401 }
)
}
if (!(await isCurrentAdmin(session))) {
return NextResponse.json(
{ error: '需要管理员权限' },
{ status: 403 }
)
}
// 获取转码队列状态
const queueStatus = transcodeQueue.getStatus()
// 统计数据库中的转码状态
const [pendingCount, processingCount, doneCount, failedCount] = await Promise.all([
prisma.material.count({
where: {
materialKind: 'VIDEO',
videoProcessingStatus: 'pending',
},
}),
prisma.material.count({
where: {
materialKind: 'VIDEO',
videoProcessingStatus: 'processing',
},
}),
prisma.material.count({
where: {
materialKind: 'VIDEO',
videoProcessingStatus: 'done',
},
}),
prisma.material.count({
where: {
materialKind: 'VIDEO',
videoProcessingStatus: 'failed',
},
}),
])
const [queuedJobCount, processingJobCount, failedJobCount] = await Promise.all([
(prisma as any).videoTranscodeJob.count({
where: { status: 'queued' },
}),
(prisma as any).videoTranscodeJob.count({
where: { status: 'processing' },
}),
(prisma as any).videoTranscodeJob.count({
where: { status: 'failed' },
}),
])
// 获取最近失败的转码任务(最多10个)
const recentFailed = await prisma.material.findMany({
where: {
materialKind: 'VIDEO',
videoProcessingStatus: 'failed',
},
select: {
id: true,
productModel: true,
categoryName: true,
sceneName: true,
createdAt: true,
updatedAt: true,
},
orderBy: {
updatedAt: 'desc',
},
take: 10,
})
return NextResponse.json({
queue: {
queueLength: queueStatus.queueLength,
processingCount: queueStatus.processingCount,
maxConcurrent: queueStatus.maxConcurrent,
processingIds: queueStatus.processingIds,
queuedIds: queueStatus.queuedIds,
},
statistics: {
pending: pendingCount,
processing: processingCount,
done: doneCount,
failed: failedCount,
total: pendingCount + processingCount + doneCount + failedCount,
},
jobs: {
queued: queuedJobCount,
processing: processingJobCount,
failed: failedJobCount,
},
recentFailed: recentFailed.map((m) => ({
id: m.id,
name: `${m.productModel}_${m.categoryName}_${m.sceneName}`,
createdAt: m.createdAt,
failedAt: m.updatedAt,
})),
})
} catch (error) {
console.error('[TranscodeStats] Error:', error)
return NextResponse.json(
{ error: '获取统计信息失败' },
{ status: 500 }
)
}
}