recappi 0.1.37 → 0.1.39

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.
package/dist/index.js CHANGED
@@ -1919,7 +1919,8 @@ function AppShell({
1919
1919
  kind: "live",
1920
1920
  session,
1921
1921
  selection,
1922
- telemetry: { ...current.telemetry, status: "recording" }
1922
+ telemetry: { ...current.telemetry, status: "recording" },
1923
+ captions: session.captionStreamEnabled ? initialLiveCaptionsState() : void 0
1923
1924
  };
1924
1925
  });
1925
1926
  }).catch((error51) => {
@@ -1936,7 +1937,8 @@ function AppShell({
1936
1937
  kind: "stopping",
1937
1938
  session: current.session,
1938
1939
  selection: current.selection,
1939
- telemetry: stoppingTelemetry
1940
+ telemetry: stoppingTelemetry,
1941
+ captions: current.captions
1940
1942
  });
1941
1943
  try {
1942
1944
  const data = await current.session.stop();
@@ -1970,11 +1972,18 @@ function AppShell({
1970
1972
  if (!liveSession) return;
1971
1973
  const session = liveSession;
1972
1974
  const unsubscribe = session.source.onEvent((event) => {
1975
+ const captionEvent = session.captionStreamEnabled ? sidecarToLiveCaptionEvent(event) : null;
1973
1976
  setLiveRecord((current) => {
1974
1977
  if (current?.kind !== "live" || current.session !== session) return current;
1975
1978
  return {
1976
1979
  ...current,
1977
- telemetry: applyRecordingEventToTelemetry(current.telemetry, event)
1980
+ telemetry: applyRecordingEventToTelemetry(current.telemetry, event),
1981
+ ...captionEvent ? {
1982
+ captions: liveCaptionReducer(
1983
+ current.captions ?? initialLiveCaptionsState(),
1984
+ captionEvent
1985
+ )
1986
+ } : {}
1978
1987
  };
1979
1988
  });
1980
1989
  });
@@ -2338,6 +2347,7 @@ function AppShell({
2338
2347
  RecordingHeroScreen,
2339
2348
  {
2340
2349
  telemetry: liveRecord.telemetry,
2350
+ captions: liveRecord.kind === "live" || liveRecord.kind === "stopping" ? liveRecord.captions : void 0,
2341
2351
  artifact: liveRecord.kind === "stopped" ? liveRecord.artifact : void 0,
2342
2352
  canTranscribe: Boolean(transcribeRecordingArtifact),
2343
2353
  now
@@ -2452,6 +2462,7 @@ var init_AppShell = __esm({
2452
2462
  init_PermissionPreflightView();
2453
2463
  init_RecordSetupView();
2454
2464
  init_RecordingHeroScreen();
2465
+ init_liveCaptions();
2455
2466
  init_recordingCore();
2456
2467
  init_format();
2457
2468
  init_terminal();
@@ -20445,6 +20456,7 @@ function createFifo(path6) {
20445
20456
  // src/record.tsx
20446
20457
  init_LiveCaptionsScreen();
20447
20458
  init_RecordingHeroScreen();
20459
+ init_liveCaptions();
20448
20460
  import { jsx as jsx4 } from "react/jsx-runtime";
20449
20461
  var SIDECAR_COMMAND_ENV = "RECAPPI_MINI_SIDECAR";
20450
20462
  var SIDECAR_HELPER_NAME = "RecappiMiniSidecar";
@@ -20466,6 +20478,7 @@ async function recordViaSidecar(opts) {
20466
20478
  source: session.source,
20467
20479
  sourceLabel: opts.includeSystemAudio === false ? "Microphone" : "System audio \xB7 all apps",
20468
20480
  micEnabled: opts.includeMicrophone !== false,
20481
+ captionStreamEnabled: session.captionStreamEnabled,
20469
20482
  renderApp: opts.runtime?.renderApp,
20470
20483
  now: opts.runtime?.now
20471
20484
  });
@@ -20504,6 +20517,7 @@ async function startLiveRecordSession(opts, selection = {
20504
20517
  });
20505
20518
  return {
20506
20519
  mode: "local",
20520
+ captionStreamEnabled: session.captionStreamEnabled,
20507
20521
  source: session.source,
20508
20522
  stop: session.stop
20509
20523
  };
@@ -20595,13 +20609,14 @@ async function startRecordSessionOnce(opts) {
20595
20609
  capabilities: opts.live ? ["recording.capture", "recording.upload", "live_captions.stream"] : ["recording.capture", "recording.upload"]
20596
20610
  })
20597
20611
  );
20612
+ const captionStreamEnabled = opts.live === true && handshake.capabilities.includes("live_captions.stream");
20598
20613
  assertSidecarCapabilities(handshake, opts);
20599
20614
  const recordingOptions = {
20600
20615
  includeSystemAudio: opts.includeSystemAudio ?? true,
20601
20616
  includeMicrophone: opts.includeMicrophone ?? true,
20602
20617
  ...opts.targetBundleId ? { targetBundleId: opts.targetBundleId } : {},
20603
20618
  ...opts.microphoneDeviceId ? { microphoneDeviceId: opts.microphoneDeviceId } : {},
20604
- liveCaptions: opts.live === true,
20619
+ liveCaptions: captionStreamEnabled,
20605
20620
  ...opts.translationLanguage ? { translationLanguage: opts.translationLanguage } : {},
20606
20621
  ...opts.transcriptionLanguage ? { transcriptionLanguage: opts.transcriptionLanguage } : {},
20607
20622
  ...opts.title ? { title: opts.title } : {}
@@ -20616,6 +20631,7 @@ async function startRecordSessionOnce(opts) {
20616
20631
  latestState = started.state;
20617
20632
  localSessionRef = started.localSessionRef;
20618
20633
  return {
20634
+ captionStreamEnabled,
20619
20635
  source: sidecar.client,
20620
20636
  stop: () => {
20621
20637
  stopPromise ??= (async () => {
@@ -20630,7 +20646,7 @@ async function startRecordSessionOnce(opts) {
20630
20646
  return recordCommandDataSchema.parse({
20631
20647
  origin: account.backendOrigin,
20632
20648
  userId: account.userId,
20633
- live: opts.live === true,
20649
+ live: captionStreamEnabled,
20634
20650
  sessionId: stopped.sessionId,
20635
20651
  state: stopped.state,
20636
20652
  ...recordingId ? { recordingId } : {},
@@ -20716,7 +20732,7 @@ function assertSidecarCapabilities(handshake, opts) {
20716
20732
  const capabilities = new Set(handshake.capabilities);
20717
20733
  const missing = [];
20718
20734
  if (!capabilities.has("recording.capture")) missing.push("recording.capture");
20719
- if (opts.live && !capabilities.has("live_captions.stream")) {
20735
+ if (opts.requireLiveCaptions && !capabilities.has("live_captions.stream")) {
20720
20736
  missing.push("live_captions.stream");
20721
20737
  }
20722
20738
  if (missing.length === 0) return;
@@ -20939,6 +20955,7 @@ function createInkRecordingHeroRenderer(opts) {
20939
20955
  source: opts.source,
20940
20956
  sourceLabel: opts.sourceLabel,
20941
20957
  micEnabled: opts.micEnabled,
20958
+ captionStreamEnabled: opts.captionStreamEnabled,
20942
20959
  onStop,
20943
20960
  now: opts.now ?? Date.now
20944
20961
  }
@@ -20957,6 +20974,7 @@ function RecordingHeroLive({
20957
20974
  source,
20958
20975
  sourceLabel,
20959
20976
  micEnabled,
20977
+ captionStreamEnabled,
20960
20978
  onStop,
20961
20979
  now
20962
20980
  }) {
@@ -20966,15 +20984,26 @@ function RecordingHeroLive({
20966
20984
  sourceLabel,
20967
20985
  micEnabled
20968
20986
  }));
20987
+ const [captions, setCaptions] = React4.useState(initialLiveCaptionsState);
20969
20988
  React4.useEffect(() => {
20970
20989
  return source.onEvent((event) => {
20971
20990
  setTelemetry((prev) => applyRecordingEventToTelemetry(prev, event));
20991
+ if (!captionStreamEnabled) return;
20992
+ const mapped = sidecarToLiveCaptionEvent(event);
20993
+ if (mapped) setCaptions((prev) => liveCaptionReducer(prev, mapped));
20972
20994
  });
20973
- }, [source]);
20995
+ }, [captionStreamEnabled, source]);
20974
20996
  useInput2((input, key) => {
20975
20997
  if (input === "q" || key.escape) onStop();
20976
20998
  });
20977
- return /* @__PURE__ */ jsx4(RecordingHeroScreen, { telemetry, now });
20999
+ return /* @__PURE__ */ jsx4(
21000
+ RecordingHeroScreen,
21001
+ {
21002
+ telemetry,
21003
+ captions: captionStreamEnabled ? captions : void 0,
21004
+ now
21005
+ }
21006
+ );
20978
21007
  }
20979
21008
 
20980
21009
  // src/cli.ts
@@ -21197,6 +21226,7 @@ async function runCli(deps = {}) {
21197
21226
  sidecarCommand: parsed.sidecarCommand,
21198
21227
  renderLive: parsed.live === true && mode === "human" && isTTY,
21199
21228
  renderHero: parsed.live !== true && mode === "human" && isTTY,
21229
+ requireLiveCaptions: parsed.live === true,
21200
21230
  runtime: deps.recordRuntime
21201
21231
  });
21202
21232
  renderSuccess("record", data, render3);