feat: wire per-port SCTE35, 8-port grid, multi-destination defaults
This commit is contained in:
parent
7cf45ceee8
commit
b3f496269c
1 changed files with 25 additions and 14 deletions
|
|
@ -16,7 +16,7 @@ export default function App() {
|
||||||
|
|
||||||
const wsUrl = `ws://${window.location.host}/ws`;
|
const wsUrl = `ws://${window.location.host}/ws`;
|
||||||
const { isConnected, lastMessage } = useWebSocket(wsUrl);
|
const { isConnected, lastMessage } = useWebSocket(wsUrl);
|
||||||
const { startRecording, stopRecording, injectSCTE35 } = useRecorder();
|
const { startRecording, stopRecording, injectSCTE35, injectSCTE35ForPort } = useRecorder();
|
||||||
|
|
||||||
// Clock
|
// Clock
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -58,6 +58,15 @@ export default function App() {
|
||||||
await injectSCTE35(eventId, durationSeconds);
|
await injectSCTE35(eventId, durationSeconds);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleInjectSCTE35ForPort = async (
|
||||||
|
portIndex: number,
|
||||||
|
eventId: number,
|
||||||
|
durationSeconds: number,
|
||||||
|
srtDestinationUrl?: string
|
||||||
|
) => {
|
||||||
|
await injectSCTE35ForPort(portIndex, eventId, durationSeconds, srtDestinationUrl);
|
||||||
|
};
|
||||||
|
|
||||||
const handleSelectPort = (portIndex: number) => {
|
const handleSelectPort = (portIndex: number) => {
|
||||||
setSelectedPort(prev => (prev === portIndex ? null : portIndex));
|
setSelectedPort(prev => (prev === portIndex ? null : portIndex));
|
||||||
};
|
};
|
||||||
|
|
@ -120,7 +129,7 @@ export default function App() {
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main style={{ padding: 28, maxWidth: 1440, margin: '0 auto' }}>
|
<main style={{ padding: 28, maxWidth: 1600, margin: '0 auto' }}>
|
||||||
|
|
||||||
{/* ── SECTION LABEL ── */}
|
{/* ── SECTION LABEL ── */}
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 18 }}>
|
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 18 }}>
|
||||||
|
|
@ -134,13 +143,8 @@ export default function App() {
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* ── PORT CARDS ── */}
|
{/* ── PORT CARDS (8-port grid: 4x2) ── */}
|
||||||
<div style={{
|
<div className="ports-grid" style={{ marginBottom: 32 }}>
|
||||||
display: 'grid',
|
|
||||||
gridTemplateColumns: 'repeat(4, 1fr)',
|
|
||||||
gap: 14,
|
|
||||||
marginBottom: 32,
|
|
||||||
}} className="ports-grid">
|
|
||||||
{ports.length === 0 ? (
|
{ports.length === 0 ? (
|
||||||
<div style={{
|
<div style={{
|
||||||
gridColumn: '1 / -1', display: 'flex', flexDirection: 'column',
|
gridColumn: '1 / -1', display: 'flex', flexDirection: 'column',
|
||||||
|
|
@ -165,6 +169,7 @@ export default function App() {
|
||||||
onStartRecording={handleStartRecording}
|
onStartRecording={handleStartRecording}
|
||||||
onStopRecording={stopRecording}
|
onStopRecording={stopRecording}
|
||||||
onOpenConfig={setConfigPort}
|
onOpenConfig={setConfigPort}
|
||||||
|
onInjectSCTE35={handleInjectSCTE35ForPort}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
|
|
@ -198,7 +203,7 @@ export default function App() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* SCTE-35 */}
|
{/* Global SCTE-35 panel */}
|
||||||
<div style={{ background: 'var(--bg-card)', border: '1px solid var(--border)', borderRadius: 4, overflow: 'hidden' }}>
|
<div style={{ background: 'var(--bg-card)', border: '1px solid var(--border)', borderRadius: 4, overflow: 'hidden' }}>
|
||||||
<div style={{
|
<div style={{
|
||||||
padding: '12px 16px', background: 'var(--bg-panel)',
|
padding: '12px 16px', background: 'var(--bg-panel)',
|
||||||
|
|
@ -206,7 +211,7 @@ export default function App() {
|
||||||
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
|
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
|
||||||
}}>
|
}}>
|
||||||
<span style={{ fontFamily: 'var(--font-ui)', fontSize: 11, fontWeight: 700, letterSpacing: '0.3em', textTransform: 'uppercase', color: 'var(--text-secondary)' }}>
|
<span style={{ fontFamily: 'var(--font-ui)', fontSize: 11, fontWeight: 700, letterSpacing: '0.3em', textTransform: 'uppercase', color: 'var(--text-secondary)' }}>
|
||||||
Ad Break Injection
|
Ad Break — All Ports
|
||||||
</span>
|
</span>
|
||||||
<span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--accent-amber)', letterSpacing: '0.08em' }}>
|
<span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--accent-amber)', letterSpacing: '0.08em' }}>
|
||||||
SCTE-35 / 104
|
SCTE-35 / 104
|
||||||
|
|
@ -236,9 +241,14 @@ export default function App() {
|
||||||
from { opacity: 0; transform: translateY(6px); }
|
from { opacity: 0; transform: translateY(6px); }
|
||||||
to { opacity: 1; transform: translateY(0); }
|
to { opacity: 1; transform: translateY(0); }
|
||||||
}
|
}
|
||||||
.ports-grid { grid-template-columns: repeat(4, 1fr); }
|
.ports-grid {
|
||||||
@media (max-width: 1100px) { .ports-grid { grid-template-columns: repeat(2, 1fr) !important; } }
|
display: grid;
|
||||||
@media (max-width: 600px) { .ports-grid { grid-template-columns: 1fr !important; } }
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
@media (max-width: 1300px) { .ports-grid { grid-template-columns: repeat(4, 1fr); } }
|
||||||
|
@media (max-width: 900px) { .ports-grid { grid-template-columns: repeat(2, 1fr); } }
|
||||||
|
@media (max-width: 500px) { .ports-grid { grid-template-columns: 1fr; } }
|
||||||
`}</style>
|
`}</style>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
@ -253,6 +263,7 @@ function defaultConfig(portIndex: number): RecorderConfig {
|
||||||
recording_path: `/recordings/port_${portIndex}_{timestamp}.mxf`,
|
recording_path: `/recordings/port_${portIndex}_{timestamp}.mxf`,
|
||||||
srt_enabled: false,
|
srt_enabled: false,
|
||||||
srt_destination: '',
|
srt_destination: '',
|
||||||
|
srt_destinations: [],
|
||||||
preview_enabled: true,
|
preview_enabled: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue