lattifai 0.4.4__py3-none-any.whl → 0.4.6__py3-none-any.whl
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.
- lattifai/__init__.py +26 -27
- lattifai/base_client.py +7 -7
- lattifai/bin/agent.py +94 -91
- lattifai/bin/align.py +110 -111
- lattifai/bin/cli_base.py +3 -3
- lattifai/bin/subtitle.py +45 -45
- lattifai/client.py +56 -56
- lattifai/errors.py +73 -73
- lattifai/io/__init__.py +12 -11
- lattifai/io/gemini_reader.py +30 -30
- lattifai/io/gemini_writer.py +17 -17
- lattifai/io/reader.py +13 -12
- lattifai/io/supervision.py +3 -3
- lattifai/io/text_parser.py +43 -16
- lattifai/io/utils.py +4 -4
- lattifai/io/writer.py +31 -19
- lattifai/tokenizer/__init__.py +1 -1
- lattifai/tokenizer/phonemizer.py +3 -3
- lattifai/tokenizer/tokenizer.py +84 -83
- lattifai/utils.py +15 -15
- lattifai/workers/__init__.py +1 -1
- lattifai/workers/lattice1_alpha.py +103 -63
- lattifai/workflows/__init__.py +11 -11
- lattifai/workflows/agents.py +2 -0
- lattifai/workflows/base.py +22 -22
- lattifai/workflows/file_manager.py +182 -182
- lattifai/workflows/gemini.py +29 -29
- lattifai/workflows/prompts/__init__.py +4 -4
- lattifai/workflows/youtube.py +233 -233
- {lattifai-0.4.4.dist-info → lattifai-0.4.6.dist-info}/METADATA +7 -10
- lattifai-0.4.6.dist-info/RECORD +39 -0
- {lattifai-0.4.4.dist-info → lattifai-0.4.6.dist-info}/licenses/LICENSE +1 -1
- lattifai-0.4.4.dist-info/RECORD +0 -39
- {lattifai-0.4.4.dist-info → lattifai-0.4.6.dist-info}/WHEEL +0 -0
- {lattifai-0.4.4.dist-info → lattifai-0.4.6.dist-info}/entry_points.txt +0 -0
- {lattifai-0.4.4.dist-info → lattifai-0.4.6.dist-info}/top_level.txt +0 -0
lattifai/__init__.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import os
|
|
2
1
|
import sys
|
|
3
2
|
import warnings
|
|
4
3
|
|
|
@@ -26,9 +25,9 @@ except ImportError:
|
|
|
26
25
|
from importlib_metadata import version
|
|
27
26
|
|
|
28
27
|
try:
|
|
29
|
-
__version__ = version(
|
|
28
|
+
__version__ = version("lattifai")
|
|
30
29
|
except Exception:
|
|
31
|
-
__version__ =
|
|
30
|
+
__version__ = "0.1.0" # fallback version
|
|
32
31
|
|
|
33
32
|
|
|
34
33
|
# Check and auto-install k2 if not present
|
|
@@ -39,15 +38,15 @@ def _check_and_install_k2():
|
|
|
39
38
|
except ImportError:
|
|
40
39
|
import subprocess
|
|
41
40
|
|
|
42
|
-
print(
|
|
41
|
+
print("k2 is not installed. Attempting to install k2...")
|
|
43
42
|
try:
|
|
44
|
-
subprocess.check_call([sys.executable,
|
|
45
|
-
subprocess.check_call([sys.executable,
|
|
43
|
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "install-k2"])
|
|
44
|
+
subprocess.check_call([sys.executable, "-m", "install_k2"])
|
|
46
45
|
import k2 # Try importing again after installation
|
|
47
46
|
|
|
48
|
-
print(
|
|
47
|
+
print("k2 installed successfully.")
|
|
49
48
|
except Exception as e:
|
|
50
|
-
warnings.warn(f
|
|
49
|
+
warnings.warn(f"Failed to install k2 automatically. Please install it manually. Error: {e}")
|
|
51
50
|
return True
|
|
52
51
|
|
|
53
52
|
|
|
@@ -57,11 +56,11 @@ _check_and_install_k2()
|
|
|
57
56
|
|
|
58
57
|
# Lazy import for LattifAI to avoid dependency issues during basic import
|
|
59
58
|
def __getattr__(name):
|
|
60
|
-
if name ==
|
|
59
|
+
if name == "LattifAI":
|
|
61
60
|
from .client import LattifAI
|
|
62
61
|
|
|
63
62
|
return LattifAI
|
|
64
|
-
if name ==
|
|
63
|
+
if name == "AsyncLattifAI":
|
|
65
64
|
from .client import AsyncLattifAI
|
|
66
65
|
|
|
67
66
|
return AsyncLattifAI
|
|
@@ -69,21 +68,21 @@ def __getattr__(name):
|
|
|
69
68
|
|
|
70
69
|
|
|
71
70
|
__all__ = [
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
71
|
+
"LattifAI", # noqa: F822
|
|
72
|
+
"AsyncLattifAI", # noqa: F822
|
|
73
|
+
"LattifAIError",
|
|
74
|
+
"AudioProcessingError",
|
|
75
|
+
"AudioLoadError",
|
|
76
|
+
"AudioFormatError",
|
|
77
|
+
"SubtitleProcessingError",
|
|
78
|
+
"SubtitleParseError",
|
|
79
|
+
"AlignmentError",
|
|
80
|
+
"LatticeEncodingError",
|
|
81
|
+
"LatticeDecodingError",
|
|
82
|
+
"ModelLoadError",
|
|
83
|
+
"DependencyError",
|
|
84
|
+
"APIError",
|
|
85
|
+
"ConfigurationError",
|
|
86
|
+
"SubtitleIO",
|
|
87
|
+
"__version__",
|
|
89
88
|
]
|
lattifai/base_client.py
CHANGED
|
@@ -23,11 +23,11 @@ class BaseAPIClient(ABC):
|
|
|
23
23
|
default_headers: Optional[Dict[str, str]] = None,
|
|
24
24
|
) -> None:
|
|
25
25
|
if api_key is None:
|
|
26
|
-
api_key = os.environ.get(
|
|
26
|
+
api_key = os.environ.get("LATTIFAI_API_KEY")
|
|
27
27
|
if api_key is None:
|
|
28
28
|
raise ConfigurationError(
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
"The api_key client option must be set either by passing api_key to the client "
|
|
30
|
+
"or by setting the LATTIFAI_API_KEY environment variable"
|
|
31
31
|
)
|
|
32
32
|
|
|
33
33
|
self._api_key = api_key
|
|
@@ -36,8 +36,8 @@ class BaseAPIClient(ABC):
|
|
|
36
36
|
self._max_retries = max_retries
|
|
37
37
|
|
|
38
38
|
headers = {
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
"User-Agent": "LattifAI/Python",
|
|
40
|
+
"Authorization": f"Bearer {self._api_key}",
|
|
41
41
|
}
|
|
42
42
|
if default_headers:
|
|
43
43
|
headers.update(default_headers)
|
|
@@ -78,7 +78,7 @@ class SyncAPIClient(BaseAPIClient):
|
|
|
78
78
|
|
|
79
79
|
def post(self, api_endpoint: str, *, json: Optional[Dict[str, Any]] = None, **kwargs) -> httpx.Response:
|
|
80
80
|
"""Make a POST request to the specified API endpoint."""
|
|
81
|
-
return self._request(
|
|
81
|
+
return self._request("POST", api_endpoint, json=json, **kwargs)
|
|
82
82
|
|
|
83
83
|
|
|
84
84
|
class AsyncAPIClient(BaseAPIClient):
|
|
@@ -123,4 +123,4 @@ class AsyncAPIClient(BaseAPIClient):
|
|
|
123
123
|
**kwargs,
|
|
124
124
|
) -> httpx.Response:
|
|
125
125
|
"""Make a POST request to the specified API endpoint."""
|
|
126
|
-
return await self._request(
|
|
126
|
+
return await self._request("POST", api_endpoint, json=json, files=files, **kwargs)
|
lattifai/bin/agent.py
CHANGED
|
@@ -5,105 +5,104 @@ Agent command for YouTube workflow
|
|
|
5
5
|
import asyncio
|
|
6
6
|
import os
|
|
7
7
|
import sys
|
|
8
|
-
from typing import
|
|
8
|
+
from typing import Optional
|
|
9
9
|
|
|
10
10
|
import click
|
|
11
11
|
import colorful
|
|
12
|
-
from lhotse.utils import Pathlike
|
|
13
12
|
|
|
14
13
|
from lattifai.bin.cli_base import cli
|
|
15
14
|
from lattifai.io import OUTPUT_SUBTITLE_FORMATS
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
@cli.command()
|
|
19
|
-
@click.option(
|
|
18
|
+
@click.option("--youtube", "--yt", is_flag=True, help="Process YouTube URL through agentic workflow.")
|
|
20
19
|
@click.option(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
"-K",
|
|
21
|
+
"-L",
|
|
22
|
+
"--api-key",
|
|
23
|
+
"--api_key",
|
|
25
24
|
type=str,
|
|
26
|
-
help=
|
|
25
|
+
help="LattifAI API key for alignment (overrides LATTIFAI_API_KEY env var).",
|
|
27
26
|
)
|
|
28
27
|
@click.option(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
"-G",
|
|
29
|
+
"--gemini-api-key",
|
|
30
|
+
"--gemini_api_key",
|
|
32
31
|
type=str,
|
|
33
|
-
help=
|
|
32
|
+
help="Gemini API key for transcription (overrides GEMINI_API_KEY env var).",
|
|
34
33
|
)
|
|
35
34
|
@click.option(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
type=click.Choice([
|
|
39
|
-
default=
|
|
40
|
-
help=
|
|
35
|
+
"-D",
|
|
36
|
+
"--device",
|
|
37
|
+
type=click.Choice(["cpu", "cuda", "mps"], case_sensitive=False),
|
|
38
|
+
default="cpu",
|
|
39
|
+
help="Device to use for inference.",
|
|
41
40
|
)
|
|
42
41
|
@click.option(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
"-M",
|
|
43
|
+
"--model-name-or-path",
|
|
44
|
+
"--model_name_or_path",
|
|
46
45
|
type=str,
|
|
47
|
-
default=
|
|
48
|
-
help=
|
|
46
|
+
default="Lattifai/Lattice-1-Alpha",
|
|
47
|
+
help="Model name or path for alignment.",
|
|
49
48
|
)
|
|
50
49
|
@click.option(
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
"--media-format",
|
|
51
|
+
"--media_format",
|
|
53
52
|
type=click.Choice(
|
|
54
|
-
[
|
|
53
|
+
["mp3", "wav", "m4a", "aac", "opus", "mp4", "webm", "mkv", "avi", "mov", "flv", "wmv", "mpeg", "mpg", "3gp"],
|
|
55
54
|
case_sensitive=False,
|
|
56
55
|
),
|
|
57
|
-
default=
|
|
58
|
-
help=
|
|
56
|
+
default="mp4",
|
|
57
|
+
help="Media format for YouTube download (audio or video).",
|
|
59
58
|
)
|
|
60
59
|
@click.option(
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
"--output-format",
|
|
61
|
+
"--output_format",
|
|
63
62
|
type=click.Choice(OUTPUT_SUBTITLE_FORMATS, case_sensitive=False),
|
|
64
|
-
default=
|
|
65
|
-
help=
|
|
63
|
+
default="srt",
|
|
64
|
+
help="Subtitle output format.",
|
|
66
65
|
)
|
|
67
66
|
@click.option(
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
"--output-dir",
|
|
68
|
+
"--output_dir",
|
|
70
69
|
type=click.Path(exists=False, file_okay=False, dir_okay=True),
|
|
71
|
-
help=
|
|
70
|
+
help="Output directory for generated files (default: current directory).",
|
|
72
71
|
)
|
|
73
72
|
@click.option(
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
"--max-retries",
|
|
74
|
+
"--max_retries",
|
|
76
75
|
type=int,
|
|
77
76
|
default=0,
|
|
78
|
-
help=
|
|
77
|
+
help="Maximum number of retries for failed steps.",
|
|
79
78
|
)
|
|
80
79
|
@click.option(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
"-S",
|
|
81
|
+
"--split-sentence",
|
|
82
|
+
"--split_sentence",
|
|
84
83
|
is_flag=True,
|
|
85
84
|
default=False,
|
|
86
|
-
help=
|
|
85
|
+
help="Re-segment subtitles by semantics.",
|
|
87
86
|
)
|
|
88
87
|
@click.option(
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
"--word-level",
|
|
89
|
+
"--word_level",
|
|
91
90
|
is_flag=True,
|
|
92
91
|
default=False,
|
|
93
|
-
help=
|
|
92
|
+
help="Include word-level alignment timestamps in output (for JSON, TextGrid, and subtitle formats).",
|
|
94
93
|
)
|
|
95
|
-
@click.option(
|
|
96
|
-
@click.option(
|
|
97
|
-
@click.argument(
|
|
94
|
+
@click.option("--verbose", "-v", is_flag=True, help="Enable verbose logging.")
|
|
95
|
+
@click.option("--force", "-f", is_flag=True, help="Force overwrite existing files without confirmation.")
|
|
96
|
+
@click.argument("url", type=str, required=True)
|
|
98
97
|
def agent(
|
|
99
98
|
youtube: bool,
|
|
100
99
|
url: str,
|
|
101
100
|
api_key: Optional[str] = None,
|
|
102
101
|
gemini_api_key: Optional[str] = None,
|
|
103
|
-
device: str =
|
|
104
|
-
model_name_or_path: str =
|
|
105
|
-
media_format: str =
|
|
106
|
-
output_format: str =
|
|
102
|
+
device: str = "cpu",
|
|
103
|
+
model_name_or_path: str = "Lattifai/Lattice-1-Alpha",
|
|
104
|
+
media_format: str = "mp4",
|
|
105
|
+
output_format: str = "srt",
|
|
107
106
|
output_dir: Optional[str] = None,
|
|
108
107
|
max_retries: int = 0,
|
|
109
108
|
split_sentence: bool = False,
|
|
@@ -121,22 +120,22 @@ def agent(
|
|
|
121
120
|
"""
|
|
122
121
|
|
|
123
122
|
if not youtube:
|
|
124
|
-
click.echo(colorful.red(
|
|
123
|
+
click.echo(colorful.red("❌ Please specify a workflow type. Use --youtube for YouTube processing."))
|
|
125
124
|
return
|
|
126
125
|
|
|
127
126
|
# Setup logging
|
|
128
127
|
import logging
|
|
129
128
|
|
|
130
129
|
log_level = logging.DEBUG if verbose else logging.INFO
|
|
131
|
-
logging.basicConfig(level=log_level, format=
|
|
130
|
+
logging.basicConfig(level=log_level, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
|
132
131
|
|
|
133
132
|
# Set default output directory
|
|
134
133
|
if not output_dir:
|
|
135
134
|
output_dir = os.getcwd()
|
|
136
135
|
|
|
137
136
|
# Get API keys
|
|
138
|
-
lattifai_api_key = api_key or os.getenv(
|
|
139
|
-
gemini_key = gemini_api_key or os.getenv(
|
|
137
|
+
lattifai_api_key = api_key or os.getenv("LATTIFAI_API_KEY")
|
|
138
|
+
gemini_key = gemini_api_key or os.getenv("GEMINI_API_KEY")
|
|
140
139
|
|
|
141
140
|
try:
|
|
142
141
|
# Run the YouTube workflow
|
|
@@ -158,7 +157,7 @@ def agent(
|
|
|
158
157
|
)
|
|
159
158
|
|
|
160
159
|
except KeyboardInterrupt:
|
|
161
|
-
click.echo(colorful.yellow(
|
|
160
|
+
click.echo(colorful.yellow("\n⚠️ Process interrupted by user"))
|
|
162
161
|
sys.exit(1)
|
|
163
162
|
except Exception as e:
|
|
164
163
|
from lattifai.errors import LattifAIError
|
|
@@ -166,12 +165,12 @@ def agent(
|
|
|
166
165
|
# Extract error message without support info (to avoid duplication)
|
|
167
166
|
if isinstance(e, LattifAIError):
|
|
168
167
|
# Use the get_message() method which includes proper formatting
|
|
169
|
-
click.echo(colorful.red(
|
|
168
|
+
click.echo(colorful.red("❌ Workflow failed:"))
|
|
170
169
|
click.echo(e.get_message())
|
|
171
170
|
# Show support info once at the end
|
|
172
171
|
click.echo(e.get_support_info())
|
|
173
172
|
else:
|
|
174
|
-
click.echo(colorful.red(f
|
|
173
|
+
click.echo(colorful.red(f"❌ Workflow failed: {str(e)}"))
|
|
175
174
|
|
|
176
175
|
if verbose:
|
|
177
176
|
import traceback
|
|
@@ -196,12 +195,12 @@ async def _run_youtube_workflow(
|
|
|
196
195
|
):
|
|
197
196
|
"""Run the YouTube processing workflow"""
|
|
198
197
|
|
|
199
|
-
click.echo(colorful.cyan(
|
|
200
|
-
click.echo(f
|
|
201
|
-
click.echo(f
|
|
202
|
-
click.echo(f
|
|
203
|
-
click.echo(f
|
|
204
|
-
click.echo(f
|
|
198
|
+
click.echo(colorful.cyan("🚀 LattifAI Agentic Workflow - YouTube Processing"))
|
|
199
|
+
click.echo(f"📺 YouTube URL: {url}")
|
|
200
|
+
click.echo(f"🎬 Media format: {media_format}")
|
|
201
|
+
click.echo(f"📝 Output format: {output_format}")
|
|
202
|
+
click.echo(f"📁 Output directory: {output_dir}")
|
|
203
|
+
click.echo(f"🔄 Max retries: {max_retries}")
|
|
205
204
|
click.echo()
|
|
206
205
|
|
|
207
206
|
# Import workflow components
|
|
@@ -235,12 +234,12 @@ async def _run_youtube_workflow(
|
|
|
235
234
|
)
|
|
236
235
|
|
|
237
236
|
# Display results
|
|
238
|
-
click.echo(colorful.bold_white_on_green(
|
|
237
|
+
click.echo(colorful.bold_white_on_green("🎉 Workflow completed successfully!"))
|
|
239
238
|
click.echo()
|
|
240
|
-
click.echo(colorful.bold_white_on_green(
|
|
239
|
+
click.echo(colorful.bold_white_on_green("📊 Results:"))
|
|
241
240
|
|
|
242
241
|
# Show metadata
|
|
243
|
-
metadata = result.get(
|
|
242
|
+
metadata = result.get("metadata", {})
|
|
244
243
|
if metadata:
|
|
245
244
|
click.echo(f'🎬 Title: {metadata.get("title", "Unknown")}')
|
|
246
245
|
click.echo(f'👤 Uploader: {metadata.get("uploader", "Unknown").strip()}')
|
|
@@ -248,18 +247,18 @@ async def _run_youtube_workflow(
|
|
|
248
247
|
click.echo()
|
|
249
248
|
|
|
250
249
|
# Show exported files
|
|
251
|
-
exported_files = result.get(
|
|
250
|
+
exported_files = result.get("exported_files", {})
|
|
252
251
|
if exported_files:
|
|
253
|
-
click.echo(colorful.bold_white_on_green(
|
|
252
|
+
click.echo(colorful.bold_white_on_green("📄 Generated subtitle files:"))
|
|
254
253
|
for format_name, file_path in exported_files.items():
|
|
255
|
-
click.echo(f
|
|
254
|
+
click.echo(f" {format_name.upper()}: {file_path}")
|
|
256
255
|
click.echo()
|
|
257
256
|
|
|
258
257
|
# Show subtitle count
|
|
259
|
-
subtitle_count = result.get(
|
|
260
|
-
click.echo(f
|
|
258
|
+
subtitle_count = result.get("subtitle_count", 0)
|
|
259
|
+
click.echo(f"📝 Generated {subtitle_count} subtitle segments")
|
|
261
260
|
|
|
262
|
-
click.echo(colorful.bold_white_on_green(
|
|
261
|
+
click.echo(colorful.bold_white_on_green("✨ All done! Your aligned subtitles are ready."))
|
|
263
262
|
|
|
264
263
|
|
|
265
264
|
# Add dependencies check
|
|
@@ -268,26 +267,26 @@ def check_dependencies():
|
|
|
268
267
|
missing_deps = []
|
|
269
268
|
|
|
270
269
|
try:
|
|
271
|
-
from google import genai
|
|
270
|
+
from google import genai # noqa: F401
|
|
272
271
|
except ImportError:
|
|
273
|
-
missing_deps.append(
|
|
272
|
+
missing_deps.append("google-genai")
|
|
274
273
|
|
|
275
274
|
try:
|
|
276
|
-
import yt_dlp
|
|
275
|
+
import yt_dlp # noqa: F401
|
|
277
276
|
except ImportError:
|
|
278
|
-
missing_deps.append(
|
|
277
|
+
missing_deps.append("yt-dlp")
|
|
279
278
|
|
|
280
279
|
try:
|
|
281
|
-
from dotenv import load_dotenv
|
|
280
|
+
from dotenv import load_dotenv # noqa: F401
|
|
282
281
|
except ImportError:
|
|
283
|
-
missing_deps.append(
|
|
282
|
+
missing_deps.append("python-dotenv")
|
|
284
283
|
|
|
285
284
|
if missing_deps:
|
|
286
|
-
click.echo(colorful.red(
|
|
285
|
+
click.echo(colorful.red("❌ Missing required dependencies:"))
|
|
287
286
|
for dep in missing_deps:
|
|
288
|
-
click.echo(f
|
|
287
|
+
click.echo(f" - {dep}")
|
|
289
288
|
click.echo()
|
|
290
|
-
click.echo(
|
|
289
|
+
click.echo("Install them with:")
|
|
291
290
|
click.echo(f' pip install {" ".join(missing_deps)}')
|
|
292
291
|
return False
|
|
293
292
|
|
|
@@ -299,20 +298,24 @@ if not check_dependencies():
|
|
|
299
298
|
pass # Don't exit on import, let the command handle it
|
|
300
299
|
|
|
301
300
|
|
|
302
|
-
if __name__ ==
|
|
301
|
+
if __name__ == "__main__":
|
|
303
302
|
import os
|
|
304
303
|
|
|
304
|
+
from dotenv import find_dotenv, load_dotenv
|
|
305
|
+
|
|
306
|
+
load_dotenv(find_dotenv(usecwd=True))
|
|
307
|
+
|
|
305
308
|
asyncio.run(
|
|
306
309
|
_run_youtube_workflow(
|
|
307
310
|
# url='https://www.youtube.com/watch?v=7nv1snJRCEI',
|
|
308
|
-
url=
|
|
309
|
-
lattifai_api_key=os.getenv(
|
|
310
|
-
gemini_api_key=os.getenv(
|
|
311
|
-
device=
|
|
312
|
-
model_name_or_path=
|
|
313
|
-
media_format=
|
|
314
|
-
output_format=
|
|
315
|
-
output_dir=
|
|
311
|
+
url="https://www.youtube.com/watch?v=DQacCB9tDaw",
|
|
312
|
+
lattifai_api_key=os.getenv("LATTIFAI_API_KEY"),
|
|
313
|
+
gemini_api_key=os.getenv("GEMINI_API_KEY", ""),
|
|
314
|
+
device="mps",
|
|
315
|
+
model_name_or_path="Lattifai/Lattice-1-Alpha",
|
|
316
|
+
media_format="mp3",
|
|
317
|
+
output_format="TextGrid",
|
|
318
|
+
output_dir="~/Downloads/lattifai_youtube",
|
|
316
319
|
max_retries=0,
|
|
317
320
|
split_sentence=True,
|
|
318
321
|
word_level=False,
|