seogitan 1.2.0 → 1.3.0

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.
@@ -1,8 +1,6 @@
1
1
  import * as http from "node:http";
2
2
  import { saveTokens } from "../lib/auth.js";
3
- // Supabase URL에서 프로젝트 ref 추출 → Vercel 배포 URL 추론
4
- // 또는 환경변수로 직접 지정 가능
5
- const WEB_URL = process.env.SEOGITAN_WEB_URL || "https://seogitan.vercel.app";
3
+ import { WEB_URL } from "../config.js";
6
4
  export function registerLoginCommand(program) {
7
5
  program
8
6
  .command("login")
@@ -5,6 +5,7 @@ import { getValidGoogleToken } from "../lib/calendar.js";
5
5
  import { checkFfmpegInstalled, listAudioDevices, createAudioRecorder, createTempOutputDir, } from "../lib/audio.js";
6
6
  import { triggerChunkTranscription } from "../lib/n8n.js";
7
7
  import { EXIT_CODES } from "../exit-codes.js";
8
+ import { WEB_URL } from "../config.js";
8
9
  import { fetchTodayEvents, linkCalendarEvent } from "seogitan-core";
9
10
  export function registerRecordCommand(program) {
10
11
  program
@@ -205,6 +206,7 @@ export function registerRecordCommand(program) {
205
206
  catch { }
206
207
  }
207
208
  console.log(`녹음 완료. Meeting ID: ${meetingId}`);
209
+ console.log(`웹에서 보기: ${WEB_URL}/meetings/${meetingId}`);
208
210
  }
209
211
  catch (err) {
210
212
  console.error(`정리 중 오류: ${err instanceof Error ? err.message : String(err)}`);
@@ -216,6 +218,7 @@ export function registerRecordCommand(program) {
216
218
  const chunkMinutes = Math.floor(chunkDurationSeconds / 60);
217
219
  console.log(`녹음 시작: ${tempTitle} (${chunkMinutes}분마다 자동 전사, Ctrl+C로 종료)`);
218
220
  console.log(`Meeting ID: ${meetingId}`);
221
+ console.log(`웹에서 보기: ${WEB_URL}/meetings/${meetingId}`);
219
222
  }
220
223
  catch (err) {
221
224
  console.error(`오류: ${err instanceof Error ? err.message : String(err)}`);
package/dist/config.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export declare const SUPABASE_URL: string;
2
2
  export declare const SUPABASE_ANON_KEY: string;
3
+ export declare const WEB_URL: string;
3
4
  export declare const SUPABASE_FUNCTIONS_URL: string;
package/dist/config.js CHANGED
@@ -6,6 +6,8 @@ export const SUPABASE_URL = process.env.SUPABASE_URL ||
6
6
  export const SUPABASE_ANON_KEY = process.env.SUPABASE_ANON_KEY ||
7
7
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY ||
8
8
  "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBuZWR3cWJidXF2aXlrbmdwZGJpIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzQ1NTc2NDYsImV4cCI6MjA5MDEzMzY0Nn0.cbLANAeWNy6XxL-dhOIdnGRV_C0c68lLM94H1-nk-fg";
9
+ // Web App URL
10
+ export const WEB_URL = process.env.SEOGITAN_WEB_URL || "https://seogitan.vercel.app";
9
11
  // Supabase Edge Functions URL
10
12
  export const SUPABASE_FUNCTIONS_URL = process.env.SUPABASE_FUNCTIONS_URL ||
11
13
  "https://pnedwqbbuqviykngpdbi.supabase.co/functions/v1";
package/dist/lib/audio.js CHANGED
@@ -26,13 +26,32 @@ export function checkFfmpegInstalled() {
26
26
  }
27
27
  }
28
28
  export function listAudioDevices() {
29
+ const ffmpeg = getFfmpegPath();
30
+ let cmd;
31
+ if (process.platform === "darwin") {
32
+ cmd = `"${ffmpeg}" -f avfoundation -list_devices true -i dummy`;
33
+ }
34
+ else if (process.platform === "win32") {
35
+ cmd = `"${ffmpeg}" -f dshow -list_devices true -i dummy`;
36
+ }
37
+ else {
38
+ // Linux: use pactl
39
+ try {
40
+ const out = execSync("pactl list short sources", { encoding: "utf-8" });
41
+ return out.split("\n").filter(Boolean).map((line, i) => ({
42
+ index: i,
43
+ name: line.split("\t")[1] || line,
44
+ }));
45
+ }
46
+ catch {
47
+ return [];
48
+ }
49
+ }
29
50
  try {
30
- // ffmpeg exits with error code when listing devices, so we must catch
31
- execSync(`"${getFfmpegPath()}" -f avfoundation -list_devices true -i dummy`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
51
+ execSync(cmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
32
52
  return [];
33
53
  }
34
54
  catch (err) {
35
- // ffmpeg writes device list to stderr even on "error" exit
36
55
  if (err && typeof err === "object" && "stderr" in err) {
37
56
  return parseAudioDevices(err.stderr);
38
57
  }
@@ -72,9 +91,16 @@ export function createAudioRecorder(options) {
72
91
  let watcher = null;
73
92
  // Build ffmpeg args based on platform
74
93
  function buildFfmpegArgs() {
75
- const inputArgs = process.platform === "darwin"
76
- ? ["-f", "avfoundation", "-i", `:${deviceIndex}`]
77
- : ["-f", "pulse", "-i", "default"];
94
+ let inputArgs;
95
+ if (process.platform === "darwin") {
96
+ inputArgs = ["-f", "avfoundation", "-i", `:${deviceIndex}`];
97
+ }
98
+ else if (process.platform === "win32") {
99
+ inputArgs = ["-f", "dshow", "-i", `audio=${deviceIndex}`];
100
+ }
101
+ else {
102
+ inputArgs = ["-f", "pulse", "-i", "default"];
103
+ }
78
104
  return [
79
105
  ...inputArgs,
80
106
  "-ar",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "seogitan",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "seogitan": "dist/index.js"