seogitan 1.1.3 → 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
@@ -132,6 +133,7 @@ export function registerRecordCommand(program) {
132
133
  audio_signed_url: signedUrlData.signedUrl,
133
134
  is_final: false,
134
135
  created_by: userId,
136
+ chunk_duration: chunkDurationSeconds,
135
137
  });
136
138
  }
137
139
  try {
@@ -189,6 +191,7 @@ export function registerRecordCommand(program) {
189
191
  audio_signed_url: signedUrlData.signedUrl,
190
192
  is_final: true,
191
193
  created_by: userId,
194
+ chunk_duration: chunkDurationSeconds,
192
195
  });
193
196
  }
194
197
  }
@@ -203,6 +206,7 @@ export function registerRecordCommand(program) {
203
206
  catch { }
204
207
  }
205
208
  console.log(`녹음 완료. Meeting ID: ${meetingId}`);
209
+ console.log(`웹에서 보기: ${WEB_URL}/meetings/${meetingId}`);
206
210
  }
207
211
  catch (err) {
208
212
  console.error(`정리 중 오류: ${err instanceof Error ? err.message : String(err)}`);
@@ -214,6 +218,7 @@ export function registerRecordCommand(program) {
214
218
  const chunkMinutes = Math.floor(chunkDurationSeconds / 60);
215
219
  console.log(`녹음 시작: ${tempTitle} (${chunkMinutes}분마다 자동 전사, Ctrl+C로 종료)`);
216
220
  console.log(`Meeting ID: ${meetingId}`);
221
+ console.log(`웹에서 보기: ${WEB_URL}/meetings/${meetingId}`);
217
222
  }
218
223
  catch (err) {
219
224
  console.error(`오류: ${err instanceof Error ? err.message : String(err)}`);
@@ -100,6 +100,7 @@ export function registerUploadCommand(program) {
100
100
  audio_signed_url: signedData.signedUrl,
101
101
  is_final: isFinal,
102
102
  created_by: userId,
103
+ chunk_duration: chunkDuration,
103
104
  });
104
105
  }
105
106
  console.log(`청크 ${i}/${chunkFiles.length - 1} 업로드 완료${isFinal ? " (최종)" : ""}`);
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/dist/lib/n8n.d.ts CHANGED
@@ -5,6 +5,7 @@ export interface ChunkUploadedPayload {
5
5
  is_final: boolean;
6
6
  created_by: string;
7
7
  attendees?: string[];
8
+ chunk_duration?: number;
8
9
  }
9
10
  export declare function triggerChunkTranscription(payload: ChunkUploadedPayload): Promise<void>;
10
11
  export declare function triggerSummarize(meetingId: string): Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "seogitan",
3
- "version": "1.1.3",
3
+ "version": "1.3.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "seogitan": "dist/index.js"