's'
This commit is contained in:
@@ -1,39 +1,2 @@
|
|||||||
https://live.douyin.com/925673220466,主播: 兜有米麻糍
|
# 每行一条源站直播页 URL(如抖音直播间),由控制台保存或手工编辑
|
||||||
https://live.douyin.com/745606325880,主播: w、(摆摊日记_)
|
# 部署后请删除本注释并填入实际地址,或仅在 Web 控制台「直播地址列表」中填写
|
||||||
https://live.douyin.com/675343045974,主播: 张子沐的串串(你的电子榨菜)
|
|
||||||
https://live.douyin.com/673565298571,主播: 轻舟已撞大冰山(摆摊vlog)
|
|
||||||
https://live.douyin.com/835571459859,主播: 海绵饱饱
|
|
||||||
https://live.douyin.com/152358755212,主播: 大美_红烧肉
|
|
||||||
https://live.douyin.com/990825651731,主播: 王同学摆摊日记(蜜汁烤鸡腿)
|
|
||||||
https://live.douyin.com/591442402624,主播: 76696515302
|
|
||||||
https://live.douyin.com/967381081829,主播: 憨憨的摆摊日记
|
|
||||||
https://live.douyin.com/78012762575,主播: 摆摊儿去划水
|
|
||||||
https://live.douyin.com/163813589919,主播: 不要熬夜(摆摊中)
|
|
||||||
https://live.douyin.com/498368994814,主播: 剪头发的小帆帆
|
|
||||||
https://live.douyin.com/617848099204,主播: 果妈要努力
|
|
||||||
https://live.douyin.com/821525628944,主播: 李熙雨⭐
|
|
||||||
https://live.douyin.com/993102287144,主播: 小茗早餐(薪笼记助创官)
|
|
||||||
https://live.douyin.com/701547125568,主播: 悠悠包
|
|
||||||
https://live.douyin.com/816130992220,主播: 甜昕冰冰的摆摊日记
|
|
||||||
https://live.douyin.com/876468215361,主播: 晓晓和凡凡
|
|
||||||
https://live.douyin.com/511335278313,主播: 秘书(摆摊休息版)
|
|
||||||
https://live.douyin.com/483160615952,主播: 小胡同学你好(饭团版)
|
|
||||||
https://live.douyin.com/525514386431,主播: 阿闯烤肉夹馍
|
|
||||||
https://live.douyin.com/8687122573,主播: 小彤炒粉
|
|
||||||
https://live.douyin.com/642534242822,主播: (小王_)煎饼果子
|
|
||||||
https://live.douyin.com/743565594721,主播: 汪汪汪小妞
|
|
||||||
https://live.douyin.com/249578288248,主播: 思思努力版
|
|
||||||
https://live.douyin.com/472140253414,主播: 戴盘龙
|
|
||||||
https://live.douyin.com/700846653732,主播: 三哥大锅菜_炒鸡(国基路店)官方号
|
|
||||||
https://live.douyin.com/81849868631,主播: 纯儿²¹(休息勿跑空哦)
|
|
||||||
https://live.douyin.com/690114366322,主播: 卤味鲜(东大)
|
|
||||||
https://live.douyin.com/469980190666,主播: 茜茜柠檬茶(小米茶档_)
|
|
||||||
https://live.douyin.com/388066418744,主播: 加速姐的摆摊日记
|
|
||||||
https://live.douyin.com/661694696687,主播: 小米摆摊记
|
|
||||||
https://live.douyin.com/228132412943,主播: 00后摆摊小可爱
|
|
||||||
https://live.douyin.com/876677865786,主播: 牛哄哄
|
|
||||||
https://live.douyin.com/573735790640,主播: 小董卤串(餐饮)
|
|
||||||
https://live.douyin.com/260608582882,主播: 阿伟在炒饭(90後炒饭)
|
|
||||||
https://live.douyin.com/210443559964,主播: 小小诺
|
|
||||||
https://live.douyin.com/305363702471,主播: 嘉嘉在摆摊
|
|
||||||
https://live.douyin.com/143239713951,主播: ɞ_大馋丫头的烤肠
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
[录制设置]
|
[录制设置]
|
||||||
language(zh_cn/en) = zh_cn
|
language(zh_cn/en) = zh_cn
|
||||||
是否跳过代理检测(是/否) = 是
|
是否跳过代理检测(是/否) = 是
|
||||||
直播保存路径(不填则默认) =
|
直播保存路径(不填则默认) =
|
||||||
@@ -49,7 +49,7 @@ SMTP邮件服务器端口 =
|
|||||||
发件人邮箱 =
|
发件人邮箱 =
|
||||||
发件人显示昵称 =
|
发件人显示昵称 =
|
||||||
收件人邮箱 =
|
收件人邮箱 =
|
||||||
ntfy推送地址 = https://ntfy.sh/xxxx
|
ntfy推送地址 =
|
||||||
ntfy推送标签 = tada
|
ntfy推送标签 = tada
|
||||||
ntfy推送邮箱 =
|
ntfy推送邮箱 =
|
||||||
pushplus推送token =
|
pushplus推送token =
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"networkName": "lr_f976289ba590",
|
"networkName": "",
|
||||||
"networkSecret": "5f86ed227e8cfcf7d8b70b287502b682aa8d3ca0b0c560ed",
|
"networkSecret": "",
|
||||||
"peerUrls": []
|
"peerUrls": []
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"redirect_uri": "http://127.0.0.1:8001/youtube/oauth/callback",
|
"redirect_uri": "http://127.0.0.1:8001/youtube/oauth/callback",
|
||||||
"web": {
|
"web": {
|
||||||
"client_id": "305371487651-iuqafultpqp0rvitojr70560k1foet0n.apps.googleusercontent.com",
|
"client_id": "",
|
||||||
"client_secret": "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",
|
"client_secret": "",
|
||||||
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
||||||
"token_uri": "https://oauth2.googleapis.com/token",
|
"token_uri": "https://oauth2.googleapis.com/token",
|
||||||
"redirect_uris": ["http://127.0.0.1:8001/youtube/oauth/callback"]
|
"redirect_uris": ["http://127.0.0.1:8001/youtube/oauth/callback"]
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
9d0103f49a3fea59311c014b9468e3ad2bd14d4f8334a7ec
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
[youtube]
|
[youtube]
|
||||||
# 必填:YouTube 直播推流 key(在 YouTube 工作室 → 创建 → 流式传输 获取)
|
# 必填:YouTube 直播推流 key(在 YouTube 工作室 → 创建 → 流式传输 获取)
|
||||||
; key = qxvb-r47b-r5ju-6ud3-6k7z
|
key =
|
||||||
key = x04z-564w-aks7-embw-30y4
|
|
||||||
|
|
||||||
# 可选:是否使用 RTMPS 加密推流,填 否 则用 RTMP(默认 RTMPS)
|
# 可选:是否使用 RTMPS 加密推流,填 否 则用 RTMP(默认 RTMPS)
|
||||||
; rtmps = 否
|
; rtmps = 否
|
||||||
@@ -10,4 +9,4 @@ key = x04z-564w-aks7-embw-30y4
|
|||||||
; bitrate = 2500
|
; bitrate = 2500
|
||||||
|
|
||||||
# 可选:软编 speed 长期小于 1 时开启——轻量音频链(无 arnndn/长 EQ),减轻 CPU。填 1 或 是
|
# 可选:软编 speed 长期小于 1 时开启——轻量音频链(无 arnndn/长 EQ),减轻 CPU。填 1 或 是
|
||||||
fast_audio = 1
|
; fast_audio = 1
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ export type PipelineStep = {
|
|||||||
sub?: string;
|
sub?: string;
|
||||||
gradient: string;
|
gradient: string;
|
||||||
target?: PortalNavTarget;
|
target?: PortalNavTarget;
|
||||||
|
/** 若设置,点击时在新标签打开(优先于 target) */
|
||||||
|
openUrl?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Props = {
|
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">
|
<div className="mt-6 flex flex-col items-center gap-4 sm:flex-row sm:flex-wrap sm:justify-center">
|
||||||
{steps.map((step, i) => (
|
{steps.map((step, i) => (
|
||||||
<div key={step.label} className="flex items-center gap-4">
|
<div key={step.label} className="flex items-center gap-4">
|
||||||
{step.target && onNavigate ? (
|
{step.openUrl || (step.target && onNavigate) ? (
|
||||||
<button
|
<button
|
||||||
type="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}`}
|
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>
|
<span>{step.label}</span>
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ const CHECK_KEY = "live-hub-tiktok-hdmi-check-v1";
|
|||||||
const NOTES_KEY = "live-hub-tiktok-hdmi-notes-v1";
|
const NOTES_KEY = "live-hub-tiktok-hdmi-notes-v1";
|
||||||
const SOURCE_MODE_KEY = "live-hub-tiktok-source-mode-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";
|
export type TiktokSourceMode = "ffmpeg" | "replay" | "srs";
|
||||||
|
|
||||||
type ReplayFileRow = { name: string; size: number; replay_url: string };
|
type ReplayFileRow = { name: string; size: number; replay_url: string };
|
||||||
@@ -92,7 +95,9 @@ export function LiveTiktokHdmiView({
|
|||||||
}: Props) {
|
}: Props) {
|
||||||
const tkEntries = useMemo(() => entries.filter(isTiktokProcess), [entries]);
|
const tkEntries = useMemo(() => entries.filter(isTiktokProcess), [entries]);
|
||||||
const processOptions = tkEntries.length ? tkEntries : 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 [replayFiles, setReplayFiles] = useState<ReplayFileRow[]>([]);
|
||||||
const [replayLoading, setReplayLoading] = useState(false);
|
const [replayLoading, setReplayLoading] = useState(false);
|
||||||
const [uploadBusy, setUploadBusy] = useState(false);
|
const [uploadBusy, setUploadBusy] = useState(false);
|
||||||
@@ -120,7 +125,10 @@ export function LiveTiktokHdmiView({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
try {
|
try {
|
||||||
const r = window.localStorage.getItem(SOURCE_MODE_KEY);
|
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 {
|
} catch {
|
||||||
/* ignore */
|
/* ignore */
|
||||||
}
|
}
|
||||||
@@ -374,8 +382,12 @@ export function LiveTiktokHdmiView({
|
|||||||
value={sourceMode}
|
value={sourceMode}
|
||||||
onChange={(e) => setSourceModePersist(e.target.value as TiktokSourceMode)}
|
onChange={(e) => setSourceModePersist(e.target.value as TiktokSourceMode)}
|
||||||
>
|
>
|
||||||
<option value="ffmpeg">FFmpeg(抖音 / TikTok 等直播间 URL)</option>
|
<option value="ffmpeg" hidden={TIKTOK_SOURCE_UI_SRS_ONLY}>
|
||||||
<option value="replay">{t("录播素材(本地上传)", "VOD upload")}</option>
|
FFmpeg(抖音 / TikTok 等直播间 URL)
|
||||||
|
</option>
|
||||||
|
<option value="replay" hidden={TIKTOK_SOURCE_UI_SRS_ONLY}>
|
||||||
|
{t("录播素材(本地上传)", "VOD upload")}
|
||||||
|
</option>
|
||||||
<option value="srs">{t("SRS(OBS 推流)", "SRS (OBS)")}</option>
|
<option value="srs">{t("SRS(OBS 推流)", "SRS (OBS)")}</option>
|
||||||
</select>
|
</select>
|
||||||
{sourceMode === "srs" ? (
|
{sourceMode === "srs" ? (
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ function isYoutubeProcess(e: ProcessEntry) {
|
|||||||
|
|
||||||
const MODE_KEY = "live-hub-youtube-mode-v1";
|
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 };
|
type LiveProcRow = { pm2: string; process_status?: string };
|
||||||
|
|
||||||
function pm2StatusOnline(st?: string) {
|
function pm2StatusOnline(st?: string) {
|
||||||
@@ -260,6 +263,10 @@ export function LiveYoutubeUnmannedView({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
try {
|
try {
|
||||||
|
if (HIDE_YOUTUBE_MULTI_PRO_TOGGLE) {
|
||||||
|
setMode("single");
|
||||||
|
return;
|
||||||
|
}
|
||||||
const m = window.localStorage.getItem(MODE_KEY);
|
const m = window.localStorage.getItem(MODE_KEY);
|
||||||
if (m === "pro" || m === "single") setMode(m);
|
if (m === "pro" || m === "single") setMode(m);
|
||||||
} catch {
|
} catch {
|
||||||
@@ -643,7 +650,7 @@ export function LiveYoutubeUnmannedView({
|
|||||||
label: "Neko",
|
label: "Neko",
|
||||||
sub: t("Chromium 工作室", "Chromium"),
|
sub: t("Chromium 工作室", "Chromium"),
|
||||||
gradient: "from-emerald-400 to-teal-500",
|
gradient: "from-emerald-400 to-teal-500",
|
||||||
target: "services",
|
openUrl: "http://live.local:9200/",
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
@@ -666,7 +673,12 @@ export function LiveYoutubeUnmannedView({
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</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
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setModePersist("single")}
|
onClick={() => setModePersist("single")}
|
||||||
|
|||||||
Reference in New Issue
Block a user