feat: panelden video izleme/indirme/silme + eşzamanlı yayın kapasitesi düzeltmesi
- streamIngest worker concurrency 3'ten sabit değildi, artık MAX_CONCURRENT_CAPTURES (varsayılan 10) ile ayarlanabiliyor. Eskiden 3'ten fazla kanal aynı anda canlıya geçerse fazlası, ilk 3'ten biri bitene kadar (saatlerce) hiç kayda alınmıyordu. - Python worker'larda (signal-detection, stt-scoring) bullmq varsayılan concurrency'si 1'di — WORKER_CONCURRENCY (varsayılan 5) ile paralelleştirildi, birden fazla kanal aynı anda segment/transkript üretirse sıraya takılmasın diye. - Frontend artık shared-media volume'üne bağlı: /api/segments/[id]/video route'u Range destekli video stream/indirme sağlıyor. Segment ve kanal detay sayfalarına <video> oynatıcı, indirme linki ve onaylı silme (RawSegment + CandidateSegment, dosya dahil) eklendi. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,8 @@ import { notFound } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
import { prisma } from "@streamclipper/db";
|
||||
import { fetchChannelStatuses } from "../../../lib/apiDaemon";
|
||||
import { deleteRawSegment, deleteCandidateSegment } from "../../actions";
|
||||
import { DeleteButton } from "../../components/DeleteButton";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
@@ -102,6 +104,17 @@ export default async function ChannelDetailPage({ params }: { params: Promise<{
|
||||
<span className={`badge ${STATUS_BADGE[segment.status] ?? "muted"}`}>{segment.status}</span>
|
||||
</div>
|
||||
|
||||
<video controls preload="metadata" style={{ width: "100%", maxWidth: "480px", marginTop: "0.5rem", borderRadius: "6px" }}>
|
||||
<source src={`/api/segments/${segment.id}/video`} type="video/mp4" />
|
||||
</video>
|
||||
|
||||
<div style={{ display: "flex", gap: "0.5rem", alignItems: "center", marginTop: "0.5rem" }}>
|
||||
<a className="badge muted" href={`/api/segments/${segment.id}/video?download=1`}>İndir</a>
|
||||
<form action={deleteRawSegment.bind(null, segment.id)}>
|
||||
<DeleteButton confirmText="Bu segmenti ve içindeki tüm aday klipleri silmek istediğine emin misin? Geri alınamaz." />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{segment.candidates.map((c) => (
|
||||
<div key={c.id} style={{ marginTop: "0.5rem", paddingLeft: "0.75rem", borderLeft: "2px solid var(--border)" }}>
|
||||
<div className="card-head">
|
||||
@@ -114,6 +127,9 @@ export default async function ChannelDetailPage({ params }: { params: Promise<{
|
||||
{transcriptPreview(c.transcriptJson) && (
|
||||
<p className="transcript-preview">{transcriptPreview(c.transcriptJson)}</p>
|
||||
)}
|
||||
<form action={deleteCandidateSegment.bind(null, c.id)} style={{ marginTop: "0.35rem" }}>
|
||||
<DeleteButton confirmText="Bu aday klibi silmek istediğine emin misin?" />
|
||||
</form>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user