dsh-vidi 0.7.7 → 0.7.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/lib/client.js +135 -134
  2. package/package.json +1 -1
package/lib/client.js CHANGED
@@ -35389,10 +35389,9 @@ function LiveView(props) {
35389
35389
  const linesBox = (0, react.useRef)(null);
35390
35390
  const fileInput = (0, react.useRef)(null);
35391
35391
  const active = !!job && (job.status === "resolving" || job.status === "running" || job.status === "stopping");
35392
- const [srcTab, setSrcTabRaw] = (0, react.useState)(() => store.get("source", "link"));
35392
+ const [srcTab, setSrcTabRaw] = (0, react.useState)("link");
35393
35393
  const setSrcTab = (v) => {
35394
35394
  setSrcTabRaw(v);
35395
- store.set("source", v);
35396
35395
  setError("");
35397
35396
  };
35398
35397
  const devices = useDevices(srcTab === "camera");
@@ -35896,20 +35895,15 @@ function LiveView(props) {
35896
35895
  title
35897
35896
  }), "device");
35898
35897
  };
35899
- const emptyBox = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
35898
+ const emptyBox = () => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
35900
35899
  className: "dshl-drop",
35901
35900
  children: [
35902
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: t(srcTab === "file" ? "src.file.title" : srcTab === "camera" ? "src.cam.title" : srcTab === "push" ? "src.push.title" : "empty.title") }),
35903
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: srcTab === "camera" && devices && !mics.length ? t("src.cam.none") : t(srcTab === "file" ? "src.file.body" : srcTab === "camera" ? "src.cam.body" : srcTab === "push" ? "src.push.body" : "empty.body") }),
35904
- srcTab === "file" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
35905
- className: "dshl-btn",
35906
- onClick: () => fileInput.current?.click(),
35907
- children: [
35908
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon.folder, {}),
35909
- " ",
35910
- t("src.file.pick")
35911
- ]
35901
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: t("empty.title") }),
35902
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
35903
+ className: "dshl-bar center",
35904
+ children: sourceBar
35912
35905
  }),
35906
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: srcTab === "camera" && devices && !mics.length ? t("src.cam.none") : t(srcTab === "file" ? "src.file.body" : srcTab === "camera" ? "src.cam.body" : srcTab === "push" ? "src.push.body" : "empty.body") }),
35913
35907
  srcTab === "push" && armed?.rtmp && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
35914
35908
  className: "dshl-pushinfo",
35915
35909
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopyRow, {
@@ -36127,6 +36121,118 @@ function LiveView(props) {
36127
36121
  children: t("lag.settings")
36128
36122
  })]
36129
36123
  }) : null;
36124
+ const sourceBar = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
36125
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pick, {
36126
+ className: "srcpick",
36127
+ value: srcTab,
36128
+ onChange: (v) => setSrcTab(v),
36129
+ title: t("src.tip"),
36130
+ options: [
36131
+ "link",
36132
+ "file",
36133
+ "camera",
36134
+ "push"
36135
+ ].map((k) => ({
36136
+ value: k,
36137
+ label: t(`src.${k}`)
36138
+ }))
36139
+ }),
36140
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
36141
+ ref: fileInput,
36142
+ type: "file",
36143
+ accept: "video/*,audio/*,.mkv,.ts,.flv",
36144
+ hidden: true,
36145
+ onChange: (e) => {
36146
+ const f = e.target.files?.[0];
36147
+ if (f) onFile(f);
36148
+ e.target.value = "";
36149
+ }
36150
+ }),
36151
+ (srcTab === "link" || srcTab === "file") && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
36152
+ className: "dshl-field",
36153
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
36154
+ type: "text",
36155
+ value: input,
36156
+ placeholder: t(srcTab === "file" ? "src.file.placeholder" : "in.placeholder"),
36157
+ onChange: (e) => setInput(e.target.value),
36158
+ onKeyDown: (e) => {
36159
+ if (e.key === "Enter") start();
36160
+ }
36161
+ }), srcTab === "file" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
36162
+ className: "ghost",
36163
+ title: t("in.file.tip"),
36164
+ onClick: () => fileInput.current?.click(),
36165
+ children: uploading !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
36166
+ className: "pct",
36167
+ children: t("in.uploading").replace("{p}", String(uploading))
36168
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon.folder, {})
36169
+ })]
36170
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
36171
+ className: "dshl-btn primary",
36172
+ onClick: () => start(),
36173
+ disabled: !classify(input),
36174
+ children: t("in.open")
36175
+ })] }),
36176
+ srcTab === "camera" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
36177
+ className: "dshl-devbar",
36178
+ children: devices === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
36179
+ className: "dshl-muted",
36180
+ children: t("src.cam.loading")
36181
+ }) : mics.length ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pick, {
36182
+ value: camV,
36183
+ options: videoOptions,
36184
+ onChange: setCamVideo,
36185
+ title: t("dev.video")
36186
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pick, {
36187
+ value: camA,
36188
+ options: mics.map((d) => ({
36189
+ value: d.id,
36190
+ label: d.name
36191
+ })),
36192
+ onChange: setCamAudio,
36193
+ title: t("dev.audio")
36194
+ })] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
36195
+ className: "dshl-muted",
36196
+ children: t("src.cam.none")
36197
+ })
36198
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
36199
+ className: "dshl-btn primary",
36200
+ onClick: () => void startDevice(),
36201
+ disabled: !camA,
36202
+ children: t("dev.start")
36203
+ })] }),
36204
+ srcTab === "push" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
36205
+ className: "dshl-field static",
36206
+ title: t("src.push.body"),
36207
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(armed?.rtmp ? "src.push.bar" : active ? "src.push.busy" : "src.push.wait") })
36208
+ }),
36209
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Settings, {
36210
+ engine: engine || "local",
36211
+ onEngine: setEngine,
36212
+ mode,
36213
+ onMode: changeMode,
36214
+ spoken,
36215
+ onSpoken: setSpoken,
36216
+ langOptions,
36217
+ login,
36218
+ onLogin: chooseLogin,
36219
+ browsers,
36220
+ providers,
36221
+ shared: keysShared,
36222
+ name: engineName,
36223
+ onKey: (id, k) => {
36224
+ setProviders((ps) => ps.map((p) => p.id === id ? {
36225
+ ...p,
36226
+ key: k,
36227
+ ready: k.set
36228
+ } : p));
36229
+ if (k.set) setError("");
36230
+ },
36231
+ open: settingsOpen,
36232
+ onOpen: setSettingsOpen,
36233
+ t
36234
+ })
36235
+ ] });
36130
36236
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36131
36237
  className: `dshl ${theater && !activeBench ? "theater" : ""} ${pageMode ? "page" : ""} ${activeBench ? "bench" : ""} ${pageMode && !sideOpen && !activeBench ? "noside" : ""}`,
36132
36238
  style: pageMode ? { ["--side-w"]: `${sideW}px` } : void 0,
@@ -36154,7 +36260,7 @@ function LiveView(props) {
36154
36260
  if (f && !active) onFile(f);
36155
36261
  },
36156
36262
  children: [
36157
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", {
36263
+ (hasMain || onClose) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", {
36158
36264
  className: "dshl-top",
36159
36265
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36160
36266
  className: "dshl-bar",
@@ -36165,117 +36271,8 @@ function LiveView(props) {
36165
36271
  title: t("page.back"),
36166
36272
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon.arrow, {})
36167
36273
  }),
36168
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pick, {
36169
- className: "srcpick",
36170
- value: srcTab,
36171
- onChange: (v) => setSrcTab(v),
36172
- title: t("src.tip"),
36173
- options: [
36174
- "link",
36175
- "file",
36176
- "camera",
36177
- "push"
36178
- ].map((k) => ({
36179
- value: k,
36180
- label: t(`src.${k}`)
36181
- }))
36182
- }),
36183
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
36184
- ref: fileInput,
36185
- type: "file",
36186
- accept: "video/*,audio/*,.mkv,.ts,.flv",
36187
- hidden: true,
36188
- onChange: (e) => {
36189
- const f = e.target.files?.[0];
36190
- if (f) onFile(f);
36191
- e.target.value = "";
36192
- }
36193
- }),
36194
- (srcTab === "link" || srcTab === "file") && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
36195
- className: "dshl-field",
36196
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
36197
- type: "text",
36198
- value: input,
36199
- placeholder: t(srcTab === "file" ? "src.file.placeholder" : "in.placeholder"),
36200
- onChange: (e) => setInput(e.target.value),
36201
- onKeyDown: (e) => {
36202
- if (e.key === "Enter") start();
36203
- }
36204
- }), srcTab === "file" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
36205
- className: "ghost",
36206
- title: t("in.file.tip"),
36207
- onClick: () => fileInput.current?.click(),
36208
- children: uploading !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
36209
- className: "pct",
36210
- children: t("in.uploading").replace("{p}", String(uploading))
36211
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon.folder, {})
36212
- })]
36213
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
36214
- className: "dshl-btn primary",
36215
- onClick: () => start(),
36216
- disabled: !classify(input),
36217
- children: t("in.open")
36218
- })] }),
36219
- srcTab === "camera" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
36220
- className: "dshl-devbar",
36221
- children: devices === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
36222
- className: "dshl-muted",
36223
- children: t("src.cam.loading")
36224
- }) : mics.length ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pick, {
36225
- value: camV,
36226
- options: videoOptions,
36227
- onChange: setCamVideo,
36228
- title: t("dev.video")
36229
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pick, {
36230
- value: camA,
36231
- options: mics.map((d) => ({
36232
- value: d.id,
36233
- label: d.name
36234
- })),
36235
- onChange: setCamAudio,
36236
- title: t("dev.audio")
36237
- })] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
36238
- className: "dshl-muted",
36239
- children: t("src.cam.none")
36240
- })
36241
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
36242
- className: "dshl-btn primary",
36243
- onClick: () => void startDevice(),
36244
- disabled: !camA,
36245
- children: t("dev.start")
36246
- })] }),
36247
- srcTab === "push" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
36248
- className: "dshl-field static",
36249
- title: t("src.push.body"),
36250
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(armed?.rtmp ? "src.push.bar" : active ? "src.push.busy" : "src.push.wait") })
36251
- }),
36252
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Settings, {
36253
- engine: engine || "local",
36254
- onEngine: setEngine,
36255
- mode,
36256
- onMode: changeMode,
36257
- spoken,
36258
- onSpoken: setSpoken,
36259
- langOptions,
36260
- login,
36261
- onLogin: chooseLogin,
36262
- browsers,
36263
- providers,
36264
- shared: keysShared,
36265
- name: engineName,
36266
- onKey: (id, k) => {
36267
- setProviders((ps) => ps.map((p) => p.id === id ? {
36268
- ...p,
36269
- key: k,
36270
- ready: k.set
36271
- } : p));
36272
- if (k.set) setError("");
36273
- },
36274
- open: settingsOpen,
36275
- onOpen: setSettingsOpen,
36276
- t
36277
- }),
36278
- pageMode && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
36274
+ hasMain && sourceBar,
36275
+ pageMode && hasMain && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
36279
36276
  className: `dshl-ctl icon ${sideOpen ? "on" : ""}`,
36280
36277
  title: t(sideOpen ? "side.hide" : "side.show"),
36281
36278
  "aria-pressed": sideOpen,
@@ -36305,15 +36302,15 @@ function LiveView(props) {
36305
36302
  children: t("st.retry")
36306
36303
  })]
36307
36304
  }),
36308
- !hasMain && !pageMode ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
36305
+ !hasMain ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
36309
36306
  className: "dshl-empty",
36310
- children: emptyBox
36307
+ children: emptyBox()
36311
36308
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("main", {
36312
36309
  className: "dshl-main",
36313
36310
  ref: mainRef,
36314
36311
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
36315
36312
  className: "dshl-col",
36316
- children: !hasMain || !job ? emptyBox : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
36313
+ children: !hasMain || !job ? emptyBox() : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
36317
36314
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Player, {
36318
36315
  ref: player,
36319
36316
  src: job.status === "resolving" || job.status === "error" ? null : `/live/media/${encodeURIComponent(job.id)}/${job.hls ?? "hls"}/index.m3u8`,
@@ -37168,7 +37165,7 @@ const en = {
37168
37165
  "in.uploading": "Uploading {p}%",
37169
37166
  "in.drop": "Drop to start",
37170
37167
  "empty.title": "Subtitles for any video",
37171
- "empty.body": "Paste a link from YouTube, Bilibili and more — videos and live streams.",
37168
+ "empty.body": "YouTube, Bilibili and other sites, videos and live streams.",
37172
37169
  "st.resolving": "Opening…",
37173
37170
  "st.login": "Using your {b} login… if macOS asks, choose “Always Allow”.",
37174
37171
  "st.live": "Live",
@@ -37188,10 +37185,10 @@ const en = {
37188
37185
  "src.push": "OBS stream",
37189
37186
  "src.file.placeholder": "Path of a video or audio file",
37190
37187
  "src.file.title": "Open a video on this computer",
37191
- "src.file.body": "Drop a video or audio file here.",
37188
+ "src.file.body": "Choose a file with the folder button, or drop it anywhere on this page.",
37192
37189
  "src.file.pick": "Choose a file",
37193
37190
  "src.cam.title": "Talk to the camera",
37194
- "src.cam.body": "Pick the picture and the microphone above and press Start: subtitles appear as you speak.",
37191
+ "src.cam.body": "Pick the picture and the microphone, press Start: subtitles appear as you speak.",
37195
37192
  "src.cam.none": "No camera or microphone found on this computer.",
37196
37193
  "src.cam.loading": "Looking for cameras…",
37197
37194
  "src.push.title": "Stream from OBS",
@@ -37586,7 +37583,7 @@ const zh = {
37586
37583
  "in.uploading": "上传中 {p}%",
37587
37584
  "in.drop": "松手开始",
37588
37585
  "empty.title": "给任何视频配字幕",
37589
- "empty.body": "粘贴 YouTube、B 站等网站的视频或直播链接",
37586
+ "empty.body": "支持 YouTube、B 站等网站的视频和直播",
37590
37587
  "st.resolving": "正在打开…",
37591
37588
  "st.login": "正在用 {b} 的登录状态…如果系统弹窗询问,点「始终允许」",
37592
37589
  "st.live": "直播中",
@@ -37606,10 +37603,10 @@ const zh = {
37606
37603
  "src.push": "OBS 推流",
37607
37604
  "src.file.placeholder": "视频或音频文件的路径",
37608
37605
  "src.file.title": "打开这台电脑上的视频",
37609
- "src.file.body": "把视频或音频文件拖到这里。",
37606
+ "src.file.body": "点文件夹按钮选择,或者直接把文件拖进来。",
37610
37607
  "src.file.pick": "选择文件",
37611
37608
  "src.cam.title": "对着摄像头说话",
37612
- "src.cam.body": "在上面选好画面和麦克风,点开始,字幕边说边出。",
37609
+ "src.cam.body": "选好画面和麦克风,点开始,字幕边说边出。",
37613
37610
  "src.cam.none": "这台电脑上没有找到摄像头或麦克风。",
37614
37611
  "src.cam.loading": "正在找摄像头…",
37615
37612
  "src.push.title": "用 OBS 推流过来",
@@ -38010,6 +38007,10 @@ const CSS = `
38010
38007
 
38011
38008
  /* ── Empty state ── */
38012
38009
  .dshl-empty { padding: 28px 20px; }
38010
+ .dshl.page .dshl-empty { flex: 1; display: flex; align-items: center; justify-content: center; min-height: 0; overflow: auto; }
38011
+ .dshl.page .dshl-empty > .dshl-drop { border: 0; padding-top: 0; }
38012
+ .dshl-drop > .dshl-bar.center { display: flex; align-items: center; gap: 8px; width: 100%; max-width: 680px; margin: 22px 0 12px; text-align: left; }
38013
+ .dshl-drop > .dshl-bar.center + p { font-size: 13px; color: var(--faint); }
38013
38014
  .dshl-drop { display: flex; flex-direction: column; align-items: center; justify-content: center; width: 100%; max-width: 760px; margin: 0 auto; padding: 56px 24px 48px;
38014
38015
  border: 1.5px dashed var(--line); border-radius: 16px; text-align: center; }
38015
38016
  .dshl-col > .dshl-drop { max-width: none; min-height: 320px; aspect-ratio: 16 / 9; padding: 32px 24px; border-radius: 12px; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-vidi",
3
- "version": "0.7.7",
3
+ "version": "0.7.8",
4
4
  "description": "A video tool for DeepSeek Harness: watch live streams, videos and podcasts with real-time subtitles in any language, then clip and download",
5
5
  "type": "module",
6
6
  "license": "PolyForm-Noncommercial-1.0.0",