Files
screenclipper/apps/frontend/app/segments/page.tsx
T
ayrisdevandClaude Sonnet 5 eccc74166a StreamClipper AI Faz 1: ingestion + sinyal analizi + STT + altyapı iskeleti
yt-dlp headless capture (15dk segmentleme), ses peak + chat velocity sinyal
tespiti, OpenAI Whisper STT (kelime zaman damgalı), BullMQ/Redis/Postgres
altyapısı ve kanal durumu + transkript kütüphanesi gösteren Next.js panel.
LLM virality skorlama, render/crop/altyazı ve multi-platform dağıtım bu
fazın kapsamı dışında.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-30 14:36:50 +03:00

70 lines
2.4 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.
import { prisma } from "@streamclipper/db";
export const dynamic = "force-dynamic";
const STATUS_BADGE: Record<string, string> = {
PENDING: "muted",
PROCESSED: "ok",
DISCARDED: "err",
PENDING_STT: "warn",
TRANSCRIBED: "ok",
FAILED: "err",
};
function transcriptPreview(transcriptJson: unknown): string | null {
if (!transcriptJson || typeof transcriptJson !== "object") return null;
const text = (transcriptJson as { text?: string }).text;
return text ? text.slice(0, 240) : null;
}
export default async function SegmentsPage() {
const segments = await prisma.rawSegment.findMany({
orderBy: { createdAt: "desc" },
take: 50,
include: { candidates: { orderBy: { createdAt: "desc" } } },
});
return (
<>
<h1>Segment & Aday Klip Kütüphanesi</h1>
{segments.length === 0 ? (
<p className="empty">Henüz işlenmiş segment yok.</p>
) : (
segments.map((segment) => (
<div className="card" key={segment.id}>
<div className="card-head">
<span className="mono">{segment.filePath}</span>
<span className={`badge ${STATUS_BADGE[segment.status] ?? "muted"}`}>{segment.status}</span>
</div>
<div className="mono">
{segment.duration}sn · {new Date(segment.startedAt).toLocaleString("tr-TR")}
</div>
{segment.candidates.length === 0 ? (
<p className="empty" style={{ marginTop: "0.5rem" }}>
Bu segmentte aday klip bulunamadı.
</p>
) : (
segment.candidates.map((c) => (
<div key={c.id} style={{ marginTop: "0.75rem", paddingLeft: "0.75rem", borderLeft: "2px solid var(--border)" }}>
<div className="card-head">
<span className="mono">
{c.startSec}s {c.endSec}s
{c.audioPeakScore != null && ` · peak ${c.audioPeakScore.toFixed(1)}dB`}
{c.chatVelocityScore != null && " · chat spike"}
</span>
<span className={`badge ${STATUS_BADGE[c.status] ?? "muted"}`}>{c.status}</span>
</div>
{transcriptPreview(c.transcriptJson) && (
<p className="transcript-preview">{transcriptPreview(c.transcriptJson)}</p>
)}
</div>
))
)}
</div>
))
)}
</>
);
}