This commit is contained in:
eric
2026-03-29 04:28:16 -05:00
parent 4fee2eb702
commit 4a1c675a60
9 changed files with 51 additions and 58 deletions

View File

@@ -16,6 +16,8 @@ export type PipelineStep = {
sub?: string;
gradient: string;
target?: PortalNavTarget;
/** 若设置,点击时在新标签打开(优先于 target */
openUrl?: string;
};
type Props = {
@@ -34,10 +36,16 @@ export function LivePipelineStrip({ t, title, subtitle, steps, onNavigate }: Pro
<div className="mt-6 flex flex-col items-center gap-4 sm:flex-row sm:flex-wrap sm:justify-center">
{steps.map((step, i) => (
<div key={step.label} className="flex items-center gap-4">
{step.target && onNavigate ? (
{step.openUrl || (step.target && onNavigate) ? (
<button
type="button"
onClick={() => onNavigate(step.target!)}
onClick={() => {
if (step.openUrl) {
window.open(step.openUrl, "_blank", "noopener,noreferrer");
return;
}
if (step.target && onNavigate) onNavigate(step.target);
}}
className={`flex min-h-[4rem] min-w-[7rem] flex-col items-center justify-center rounded-2xl bg-gradient-to-br px-4 py-2 text-center text-xs font-bold text-white shadow-lg ring-2 ring-white/10 transition hover:ring-violet-400/50 hover:brightness-110 ${step.gradient}`}
>
<span>{step.label}</span>

View File

@@ -48,6 +48,9 @@ const CHECK_KEY = "live-hub-tiktok-hdmi-check-v1";
const NOTES_KEY = "live-hub-tiktok-hdmi-notes-v1";
const SOURCE_MODE_KEY = "live-hub-tiktok-source-mode-v1";
/** UI 仅展示 SRS 选项ffmpeg/replay 的 option 保留 hidden改 false 即可恢复) */
const TIKTOK_SOURCE_UI_SRS_ONLY = true;
export type TiktokSourceMode = "ffmpeg" | "replay" | "srs";
type ReplayFileRow = { name: string; size: number; replay_url: string };
@@ -92,7 +95,9 @@ export function LiveTiktokHdmiView({
}: Props) {
const tkEntries = useMemo(() => entries.filter(isTiktokProcess), [entries]);
const processOptions = tkEntries.length ? tkEntries : entries;
const [sourceMode, setSourceMode] = useState<TiktokSourceMode>("ffmpeg");
const [sourceMode, setSourceMode] = useState<TiktokSourceMode>(
TIKTOK_SOURCE_UI_SRS_ONLY ? "srs" : "ffmpeg",
);
const [replayFiles, setReplayFiles] = useState<ReplayFileRow[]>([]);
const [replayLoading, setReplayLoading] = useState(false);
const [uploadBusy, setUploadBusy] = useState(false);
@@ -120,7 +125,10 @@ export function LiveTiktokHdmiView({
useEffect(() => {
try {
const r = window.localStorage.getItem(SOURCE_MODE_KEY);
if (r === "ffmpeg" || r === "replay" || r === "srs") setSourceMode(r);
if (r === "ffmpeg" || r === "replay" || r === "srs") {
if (TIKTOK_SOURCE_UI_SRS_ONLY && (r === "ffmpeg" || r === "replay")) setSourceMode("srs");
else setSourceMode(r);
}
} catch {
/* ignore */
}
@@ -374,8 +382,12 @@ export function LiveTiktokHdmiView({
value={sourceMode}
onChange={(e) => setSourceModePersist(e.target.value as TiktokSourceMode)}
>
<option value="ffmpeg">FFmpeg / TikTok URL</option>
<option value="replay">{t("录播素材(本地上传)", "VOD upload")}</option>
<option value="ffmpeg" hidden={TIKTOK_SOURCE_UI_SRS_ONLY}>
FFmpeg / TikTok URL
</option>
<option value="replay" hidden={TIKTOK_SOURCE_UI_SRS_ONLY}>
{t("录播素材(本地上传)", "VOD upload")}
</option>
<option value="srs">{t("SRSOBS 推流)", "SRS (OBS)")}</option>
</select>
{sourceMode === "srs" ? (

View File

@@ -35,6 +35,9 @@ function isYoutubeProcess(e: ProcessEntry) {
const MODE_KEY = "live-hub-youtube-mode-v1";
/** UI 暂时隐藏「多频道 Pro」切换DOM 与逻辑保留,改 false 即可恢复) */
const HIDE_YOUTUBE_MULTI_PRO_TOGGLE = true;
type LiveProcRow = { pm2: string; process_status?: string };
function pm2StatusOnline(st?: string) {
@@ -260,6 +263,10 @@ export function LiveYoutubeUnmannedView({
useEffect(() => {
try {
if (HIDE_YOUTUBE_MULTI_PRO_TOGGLE) {
setMode("single");
return;
}
const m = window.localStorage.getItem(MODE_KEY);
if (m === "pro" || m === "single") setMode(m);
} catch {
@@ -643,7 +650,7 @@ export function LiveYoutubeUnmannedView({
label: "Neko",
sub: t("Chromium 工作室", "Chromium"),
gradient: "from-emerald-400 to-teal-500",
target: "services",
openUrl: "http://live.local:9200/",
},
]}
/>
@@ -666,7 +673,12 @@ export function LiveYoutubeUnmannedView({
</p>
</div>
</div>
<div className="flex rounded-xl border border-white/10 bg-black/30 p-1">
<div
className={`flex rounded-xl border border-white/10 bg-black/30 p-1 ${
HIDE_YOUTUBE_MULTI_PRO_TOGGLE ? "hidden" : ""
}`}
aria-hidden={HIDE_YOUTUBE_MULTI_PRO_TOGGLE}
>
<button
type="button"
onClick={() => setModePersist("single")}