lomasub 0.1.2 → 0.1.3

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/README.md CHANGED
@@ -20,7 +20,7 @@ For a Node.js project, run `npm install lomasub`. For a persistent CLI, run `npm
20
20
  ```bash
21
21
  lomasub transcribe video.mp4 --output video.srt
22
22
  lomasub transcribe video.mp4 --speaker-diarization --srt-max-chars 48 --srt-cue-words 6
23
- lomasub transcribe video.mp4 --config options.json --no-revise-srt
23
+ lomasub transcribe video.mp4 --config options.json
24
24
  lomasub transcribe video.mp4 --no-ffmpeg
25
25
  lomasub download <job-id> --output video.srt
26
26
  lomasub --help
@@ -42,7 +42,7 @@ When ffmpeg is on `PATH`, audio is extracted into a temporary Matroska audio fil
42
42
  }
43
43
  ```
44
44
 
45
- Every current transcription config field has a kebab-case flag. Boolean fields support `--name` and `--no-name`. Explicit flags override JSON values, including `false` and `0`. Unset settings use server defaults; the API validates settings and reports retired names. Additional config keys pass through unchanged.
45
+ Supported transcription flags use kebab-case. Use `--promodel pro` (SDK: `config: { promodel: "pro" }`) for word correction before alignment. Revision settings (`revise_srt`, `revise_speakername`, `srt_revision_backend`) are not supported by this CLI/SDK, including through `--config` JSON. Boolean fields support `--name` and `--no-name`. Explicit flags override JSON values, including `false` and `0`. Unset settings use server defaults; the API validates settings and reports retired names. Other additional config keys pass through unchanged.
46
46
 
47
47
  | Settings | CLI flags |
48
48
  | --- | --- |
@@ -50,10 +50,11 @@ Every current transcription config field has a kebab-case flag. Boolean fields s
50
50
  | VAD | `--min-vad-duration-seconds`, `--max-vad-duration-seconds`, `--vad-threshold` |
51
51
  | Subtitle cues | `--min-srt-duration-ms`, `--srt-max-chars`, `--srt-cue-words` |
52
52
  | Diarization | `--speaker-diarization`, `--speaker-local-distance-threshold`, `--speaker-merge-distance-threshold`, `--speaker-clustering-drop-dialogue-percentile`, `--agglomeration-min-appear`, `--agglomolation-group-size` |
53
- | Revision | `--revise-srt`, `--revise-speakername`, `--srt-revision-backend` (`agy`, `codex`) |
54
53
 
55
54
  `--filename`, `--language`, and `--duration-seconds` are job metadata, outside config. The original local filename is preserved unless overridden. An explicit duration is forwarded to upload preparation and job creation; duration is not automatically measured.
56
55
 
56
+ The server defaults omitted, null, or blank language to `th`; `--language en` overrides it. The Thai hint permits Thai, English, and mixed transcripts: readable English is not discarded because of its script. This is a model hint, not automatic language detection.
57
+
57
58
  Use `--endpoint http://localhost:8080` for another API server. The default is `https://api.lomasub.ai`. Bearer credentials are sent only to the API, never to storage upload/download URLs.
58
59
 
59
60
  ## SDK
package/cli.js CHANGED
@@ -17,6 +17,24 @@ for (const [key, type] of Object.entries(TRANSCRIPTION_OPTIONS)) {
17
17
  if (type === 'boolean') options[`no-${flag}`] = { type: 'boolean' };
18
18
  }
19
19
 
20
+ // Display-only production defaults; omitted options still use the API's settings.
21
+ const DEFAULT_HELP = {
22
+ forcealigner_level: 'default; choices: default, llmsplitting, none',
23
+ promodel: 'disabled (omitted/null); use pro to enable word correction',
24
+ min_vad_duration_seconds: '10',
25
+ max_vad_duration_seconds: '25',
26
+ vad_threshold: '0.30',
27
+ min_srt_duration_ms: '1200',
28
+ srt_max_chars: '48',
29
+ srt_cue_words: '6',
30
+ speaker_diarization: 'disabled',
31
+ speaker_local_distance_threshold: '0.60',
32
+ speaker_merge_distance_threshold: '0.35',
33
+ speaker_clustering_drop_dialogue_percentile: '0.02',
34
+ agglomeration_min_appear: '5',
35
+ agglomolation_group_size: '300',
36
+ };
37
+
20
38
  function number(value, flag) {
21
39
  const parsed = Number(value);
22
40
  if (!value.trim() || !Number.isFinite(parsed)) throw new Error(`--${flag} requires a number.`);
@@ -32,17 +50,20 @@ async function main() {
32
50
 
33
51
  Set LOMA_API_SECRET_KEY before running. Default endpoint: https://api.lomasub.ai
34
52
  Options:
35
- --endpoint <url> API endpoint
36
53
  --output, -o <path> Output SRT (default: beside input)
37
54
  --overwrite Replace existing output
38
55
  --no-ffmpeg Upload original without audio extraction
39
- --language <code> Audio language
56
+ --language <code> ASR language hint: th, en; server default: th
40
57
  --filename <name> Job display filename
41
- --duration-seconds N Optional media duration hint
42
58
  --config <path> JSON transcription config; explicit flags override it
43
59
 
44
- Transcription options (unset values use server defaults):
45
- ${Object.entries(TRANSCRIPTION_OPTIONS).map(([key, type]) => ` --${key.replaceAll('_', '-')}${type === 'boolean' ? ' / --no-' + key.replaceAll('_', '-') : ' <' + type + '>'}`).join('\n')}`);
60
+ Transcription options:
61
+ Defaults shown are for api.lomasub.ai; omitted options use server settings.
62
+ ${Object.entries(TRANSCRIPTION_OPTIONS).map(([key, type]) => {
63
+ const flag = key.replaceAll('_', '-');
64
+ const label = `--${flag}${type === 'boolean' ? ` / --no-${flag}` : ` <${type}>`}`;
65
+ return ` ${label.padEnd(56)}default: ${DEFAULT_HELP[key]}`;
66
+ }).join('\n')}`);
46
67
  return;
47
68
  }
48
69
  const [command, input] = positionals;
package/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export interface TranscriptionConfig {
2
+ promodel?: 'pro' | null;
2
3
  forcealigner_level?: 'default' | 'llmsplitting' | 'none';
3
4
  min_vad_duration_seconds?: number;
4
5
  max_vad_duration_seconds?: number;
@@ -12,9 +13,6 @@ export interface TranscriptionConfig {
12
13
  speaker_clustering_drop_dialogue_percentile?: number;
13
14
  agglomeration_min_appear?: number;
14
15
  agglomolation_group_size?: number;
15
- revise_srt?: boolean;
16
- revise_speakername?: boolean;
17
- srt_revision_backend?: 'agy' | 'codex';
18
16
  [key: string]: unknown;
19
17
  }
20
18
 
package/index.js CHANGED
@@ -13,6 +13,7 @@ const run = promisify(execFile);
13
13
  // Shared with the CLI; validation and transcription defaults belong to the API.
14
14
  export const TRANSCRIPTION_OPTIONS = {
15
15
  forcealigner_level: 'string',
16
+ promodel: 'string',
16
17
  min_vad_duration_seconds: 'number',
17
18
  max_vad_duration_seconds: 'number',
18
19
  vad_threshold: 'number',
@@ -25,9 +26,6 @@ export const TRANSCRIPTION_OPTIONS = {
25
26
  speaker_clustering_drop_dialogue_percentile: 'number',
26
27
  agglomeration_min_appear: 'number',
27
28
  agglomolation_group_size: 'number',
28
- revise_srt: 'boolean',
29
- revise_speakername: 'boolean',
30
- srt_revision_backend: 'string',
31
29
  };
32
30
 
33
31
  const MIME_TYPES = {
@@ -69,6 +67,9 @@ export class LomaClient {
69
67
  async submitFile(file, options = {}) {
70
68
  const { signal, onProgress = () => {}, ffmpeg = true, config, language, duration_seconds } = options;
71
69
  signal?.throwIfAborted();
70
+ for (const key of ['revise_srt', 'revise_speakername', 'srt_revision_backend']) {
71
+ if (config && Object.hasOwn(config, key)) throw new Error(`config.${key} is not supported by the CLI/SDK.`);
72
+ }
72
73
  const original = resolve(file);
73
74
  if (!(await stat(original)).isFile()) throw new Error(`Not a regular file: ${file}`);
74
75
  let source = original;
@@ -88,10 +89,12 @@ export class LomaClient {
88
89
  }
89
90
  }
90
91
  signal?.throwIfAborted();
92
+ const size_bytes = (await stat(source)).size;
91
93
  const upload = await this.request('/presigned-url', {
92
94
  filename: basename(source),
93
95
  content_type: MIME_TYPES[extname(source).toLowerCase()] ?? 'application/octet-stream',
94
96
  duration_seconds,
97
+ size_bytes,
95
98
  }, signal);
96
99
  if (upload.method !== 'PUT' || !upload.upload_url || !upload.source_url || !upload.headers) {
97
100
  throw new Error('Invalid /presigned-url response.');
@@ -100,7 +103,7 @@ export class LomaClient {
100
103
  const stream = createReadStream(source);
101
104
  try {
102
105
  const response = await checkedFetch(upload.upload_url, {
103
- method: upload.method, headers: { ...upload.headers, 'Content-Length': String((await stat(source)).size) },
106
+ method: upload.method, headers: { ...upload.headers, 'Content-Length': String(size_bytes) },
104
107
  body: stream, duplex: 'half', signal,
105
108
  }, 'Upload');
106
109
  await response.arrayBuffer();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lomasub",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Lomasub cli is a command-line tool for creating subtitles from local audio or video in Node.js or the terminal, using lomasub.ai cloud service. ",
5
5
  "type": "module",
6
6
  "engines": { "node": ">=20" },