kinescript-elevenlabs 0.1.0__tar.gz

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.
@@ -0,0 +1,25 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dr. Know How
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ The fonts in kinescript/fonts/ (Space Grotesk, IBM Plex Mono) are not covered by
24
+ this license. They are distributed under the SIL Open Font License 1.1; see the
25
+ -OFL.txt files next to them.
@@ -0,0 +1,88 @@
1
+ Metadata-Version: 2.4
2
+ Name: kinescript-elevenlabs
3
+ Version: 0.1.0
4
+ Summary: ElevenLabs voices for kine voice: audio tags such as whispers, any voice in your account, and word times
5
+ Author: Dr. Know How
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/drknowhow/kinescript/tree/main/plugins/kinescript-elevenlabs
8
+ Project-URL: Documentation, https://drknowhow.github.io/kinescript/
9
+ Project-URL: Source, https://github.com/drknowhow/kinescript/tree/main/plugins/kinescript-elevenlabs
10
+ Project-URL: Issues, https://github.com/drknowhow/kinescript/issues
11
+ Project-URL: Changelog, https://github.com/drknowhow/kinescript/blob/main/CHANGELOG.md
12
+ Keywords: kinescript,elevenlabs,text to speech,tts,voice-over,audio tags,word timestamps
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
24
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
25
+ Classifier: Topic :: Multimedia :: Video
26
+ Requires-Python: >=3.10
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Dynamic: license-file
30
+
31
+ # kinescript-elevenlabs
32
+
33
+ [ElevenLabs](https://elevenlabs.io) voices for `kine voice`. It speaks the `text` of a scene's sounds through
34
+ ElevenLabs' API into WAV files and writes the time of each word, so layers can start on a word and captions follow
35
+ the voice. Eleven v4 and v3 act on audio tags such as `[whispers]`, `[laughs]` or `[sighs]`.
36
+
37
+ ```json
38
+ {"id": "vo1", "role": "voice", "backend": "elevenlabs", "speaker": "George",
39
+ "text": "[whispers] Nobody knows yet. [[go]][laughs] Render it.", "options": {"stability": 0.3}}
40
+ ```
41
+
42
+ ```bash
43
+ kine voice scene.json # writes voice/vo1.wav and voice/vo1.words.json
44
+ kine check scene.json
45
+ ```
46
+
47
+ ## Install
48
+
49
+ It needs Kinescript 1.3 or newer. It has no dependencies of its own, so it installs next to Kinescript on any
50
+ Python 3.10 or newer:
51
+
52
+ ```bash
53
+ pip install kinescript-elevenlabs
54
+ ```
55
+
56
+ From a checkout of [Kinescript](https://github.com/drknowhow/kinescript), `pip install ./plugins/kinescript-elevenlabs`
57
+ does the same.
58
+
59
+ It needs an API key from your ElevenLabs account (Developers > API keys) in `ELEVENLABS_API_KEY`. Every line it
60
+ speaks uses characters of that account's quota. `kine voice` speaks a line again only when its text, speaker, rate,
61
+ backend or options changed, so re-running it on an unchanged scene costs nothing.
62
+
63
+ ## Voices and settings
64
+
65
+ `speaker` is a voice id, or the name of a voice in your account (`George`, `Aria`); George unless the sound names one.
66
+ `rate` sets ElevenLabs' speed, which takes 0.7 to 1.2; a rate outside that is spoken at 1 and listed under
67
+ `ignored`.
68
+
69
+ `options` passes these on:
70
+
71
+ - `model`: `eleven_v4` by default. `eleven_v3` also acts on tags; other models, such as `eleven_multilingual_v2`
72
+ or `eleven_flash_v2_5`, get the text without its tags.
73
+ - `stability`, `similarity_boost`, `style`, `use_speaker_boost`: ElevenLabs' voice settings. Lower stability gives
74
+ a wider emotional range.
75
+ - `seed`, `language_code`, `apply_text_normalization`: passed to the request as they are.
76
+
77
+ An option it does not know is listed under `ignored` in what `kine voice` prints.
78
+
79
+ ## Word times
80
+
81
+ ElevenLabs returns the time of each character it says; the plugin joins them into the words of the text as written,
82
+ leaving tags out and timing each word from its first letter to its last. When a model returns no character times,
83
+ the plugin asks ElevenLabs' forced alignment for them, which is billed like speech to text.
84
+
85
+ ## Another Python
86
+
87
+ To run it from a Python other than Kinescript's, set `KINE_VOICE_CMD_ELEVENLABS` to that Python and the module:
88
+ `["/path/to/python", "-m", "kinescript_elevenlabs"]`.
@@ -0,0 +1,58 @@
1
+ # kinescript-elevenlabs
2
+
3
+ [ElevenLabs](https://elevenlabs.io) voices for `kine voice`. It speaks the `text` of a scene's sounds through
4
+ ElevenLabs' API into WAV files and writes the time of each word, so layers can start on a word and captions follow
5
+ the voice. Eleven v4 and v3 act on audio tags such as `[whispers]`, `[laughs]` or `[sighs]`.
6
+
7
+ ```json
8
+ {"id": "vo1", "role": "voice", "backend": "elevenlabs", "speaker": "George",
9
+ "text": "[whispers] Nobody knows yet. [[go]][laughs] Render it.", "options": {"stability": 0.3}}
10
+ ```
11
+
12
+ ```bash
13
+ kine voice scene.json # writes voice/vo1.wav and voice/vo1.words.json
14
+ kine check scene.json
15
+ ```
16
+
17
+ ## Install
18
+
19
+ It needs Kinescript 1.3 or newer. It has no dependencies of its own, so it installs next to Kinescript on any
20
+ Python 3.10 or newer:
21
+
22
+ ```bash
23
+ pip install kinescript-elevenlabs
24
+ ```
25
+
26
+ From a checkout of [Kinescript](https://github.com/drknowhow/kinescript), `pip install ./plugins/kinescript-elevenlabs`
27
+ does the same.
28
+
29
+ It needs an API key from your ElevenLabs account (Developers > API keys) in `ELEVENLABS_API_KEY`. Every line it
30
+ speaks uses characters of that account's quota. `kine voice` speaks a line again only when its text, speaker, rate,
31
+ backend or options changed, so re-running it on an unchanged scene costs nothing.
32
+
33
+ ## Voices and settings
34
+
35
+ `speaker` is a voice id, or the name of a voice in your account (`George`, `Aria`); George unless the sound names one.
36
+ `rate` sets ElevenLabs' speed, which takes 0.7 to 1.2; a rate outside that is spoken at 1 and listed under
37
+ `ignored`.
38
+
39
+ `options` passes these on:
40
+
41
+ - `model`: `eleven_v4` by default. `eleven_v3` also acts on tags; other models, such as `eleven_multilingual_v2`
42
+ or `eleven_flash_v2_5`, get the text without its tags.
43
+ - `stability`, `similarity_boost`, `style`, `use_speaker_boost`: ElevenLabs' voice settings. Lower stability gives
44
+ a wider emotional range.
45
+ - `seed`, `language_code`, `apply_text_normalization`: passed to the request as they are.
46
+
47
+ An option it does not know is listed under `ignored` in what `kine voice` prints.
48
+
49
+ ## Word times
50
+
51
+ ElevenLabs returns the time of each character it says; the plugin joins them into the words of the text as written,
52
+ leaving tags out and timing each word from its first letter to its last. When a model returns no character times,
53
+ the plugin asks ElevenLabs' forced alignment for them, which is billed like speech to text.
54
+
55
+ ## Another Python
56
+
57
+ To run it from a Python other than Kinescript's, set `KINE_VOICE_CMD_ELEVENLABS` to that Python and the module:
58
+ `["/path/to/python", "-m", "kinescript_elevenlabs"]`.
@@ -0,0 +1,157 @@
1
+ """ElevenLabs voices for `kine voice`: ElevenLabs' API speaks a sound's text, Eleven v4 and v3 with audio tags such
2
+ as [whispers] or [laughs], and times each character it says; those times become the words.
3
+
4
+ It needs an API key in ELEVENLABS_API_KEY, and every line it speaks uses characters of that account's quota.
5
+ kine voice calls synth(req) through the "kinescript.voice" entry point; the package has no dependencies, so it
6
+ installs next to Kinescript in any Python it runs on.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import base64
11
+ import json
12
+ import os
13
+ import re
14
+ import urllib.error
15
+ import urllib.request
16
+ import uuid
17
+ import wave
18
+ from importlib.metadata import PackageNotFoundError, version
19
+
20
+ API = "https://api.elevenlabs.io"
21
+ MODEL = "eleven_v4"
22
+ SPEAKER = "JBFqnCBsd6RMkjVDRZzb" # George, the voice in ElevenLabs' own examples
23
+ RATE = 24000 # pcm_24000: raw 16-bit mono, on every plan
24
+ TAG = re.compile(r"(?<!\[)\[(?!\[)[^\[\]()]+\](?![\](])") # as kinescript.voice.TAG
25
+ SETTINGS = {"stability", "similarity_boost", "style", "use_speaker_boost"} # voice_settings
26
+ BODY = {"seed", "language_code", "apply_text_normalization"}
27
+ SPEED = (0.7, 1.2) # what voice_settings.speed takes
28
+
29
+
30
+ def acts_on_tags(model: str) -> bool:
31
+ return model.startswith(("eleven_v3", "eleven_v4"))
32
+
33
+
34
+ def _key() -> str:
35
+ key = os.environ.get("ELEVENLABS_API_KEY") or os.environ.get("XI_API_KEY")
36
+ if not key:
37
+ raise RuntimeError("set ELEVENLABS_API_KEY to an ElevenLabs API key (elevenlabs.io > Developers > API keys)")
38
+ return key
39
+
40
+
41
+ def _call(path: str, key: str, body: bytes | None = None, ctype: str = "application/json") -> dict:
42
+ req = urllib.request.Request(API + path, data=body, method="POST" if body is not None else "GET",
43
+ headers={"xi-api-key": key, "Content-Type": ctype, "Accept": "application/json"})
44
+ try:
45
+ with urllib.request.urlopen(req, timeout=300) as r:
46
+ return json.loads(r.read())
47
+ except urllib.error.HTTPError as e:
48
+ detail = e.read().decode("utf-8", "replace")[:600]
49
+ raise RuntimeError(f"ElevenLabs {path.split('?')[0]} answered {e.code}: {detail}") from None
50
+
51
+
52
+ def voice_id(name: str, key: str) -> str:
53
+ """A voice id as given, or the id of the account's voice with that name (\"George\")."""
54
+ if re.fullmatch(r"[A-Za-z0-9]{20}", name):
55
+ return name
56
+ voices = _call("/v1/voices", key).get("voices") or []
57
+ for v in voices:
58
+ if v.get("name", "").split(" - ")[0].strip().lower() == name.strip().lower():
59
+ return v["voice_id"]
60
+ names = ", ".join(sorted(v.get("name", "").split(" - ")[0] for v in voices)[:30])
61
+ raise ValueError(f"no ElevenLabs voice named '{name}' in this account; its voices: {names or 'none'}")
62
+
63
+
64
+ def words_from_chars(chars: list[str], starts: list[float], ends: list[float], offset: float = 0.0) -> list[dict]:
65
+ """ElevenLabs' character times -> [{"word", "start", "end"}], split where the text has spaces, as the text
66
+ reads. Tags are not words; a word's time runs from its first letter to its last, so punctuation and the pause
67
+ after it are not stretched in."""
68
+ text = "".join(chars)
69
+ at, hidden = 0, [False] * len(chars)
70
+ spans = [m.span() for m in TAG.finditer(text)]
71
+ for k, c in enumerate(chars):
72
+ hidden[k] = any(a <= at < b for a, b in spans)
73
+ at += len(c)
74
+ out, cur = [], None
75
+ for c, s, e, h in zip(chars, starts, ends, hidden):
76
+ if h or c.isspace():
77
+ if cur and cur["word"]:
78
+ out.append(cur)
79
+ cur = None
80
+ continue
81
+ cur = cur or {"word": "", "start": None, "end": None}
82
+ cur["word"] += c
83
+ if re.search(r"\w", c):
84
+ cur["start"] = s if cur["start"] is None else cur["start"]
85
+ cur["end"] = e
86
+ if cur and cur["word"]:
87
+ out.append(cur)
88
+ timed, last = [], offset
89
+ for w in out:
90
+ if not re.search(r"\w", w["word"]): # punctuation on its own ("—"): nothing is said
91
+ continue
92
+ start, end = (w["start"] + offset, w["end"] + offset) if w["start"] is not None else (last, last)
93
+ timed.append({"word": w["word"], "start": round(start, 4), "end": round(end, 4)})
94
+ last = end
95
+ return timed
96
+
97
+
98
+ def _wav(path: str, pcm: bytes) -> None:
99
+ with wave.open(path, "wb") as f:
100
+ f.setnchannels(1)
101
+ f.setsampwidth(2)
102
+ f.setframerate(RATE)
103
+ f.writeframes(pcm)
104
+
105
+
106
+ def _forced(path: str, text: str, key: str) -> list[dict]:
107
+ """Words timed by ElevenLabs' forced alignment, for a model that returned no character times."""
108
+ b = uuid.uuid4().hex
109
+ with open(path, "rb") as f:
110
+ audio = f.read()
111
+ body = (f"--{b}\r\nContent-Disposition: form-data; name=\"text\"\r\n\r\n{text}\r\n"
112
+ f"--{b}\r\nContent-Disposition: form-data; name=\"file\"; filename=\"voice.wav\"\r\n"
113
+ "Content-Type: audio/wav\r\n\r\n").encode() + audio + f"\r\n--{b}--\r\n".encode()
114
+ got = _call("/v1/forced-alignment", key, body, f"multipart/form-data; boundary={b}")
115
+ return [{"word": w["text"].strip(), "start": round(w["start"], 4), "end": round(w["end"], 4)}
116
+ for w in got.get("words") or [] if re.search(r"\w", w.get("text", ""))]
117
+
118
+
119
+ def _version(model: str) -> str:
120
+ try:
121
+ own = version("kinescript-elevenlabs")
122
+ except PackageNotFoundError:
123
+ own = "?"
124
+ return f"{model}, kinescript-elevenlabs {own}"
125
+
126
+
127
+ def synth(req: dict) -> dict:
128
+ """Speak req["tagged"] (or req["text"] on a model without tags) with the voice req["speaker"] names (an id or
129
+ a name in the account, George unless named) into the WAV req["out"], and time each word."""
130
+ key = _key()
131
+ opts = dict(req.get("options") or {})
132
+ model = str(opts.pop("model", MODEL))
133
+ tags = acts_on_tags(model)
134
+ text = (req.get("tagged") or req["text"]) if tags else req["text"]
135
+ speaker = req.get("speaker") or SPEAKER
136
+ ignored = [f"options.{k}" for k in opts if k not in SETTINGS | BODY]
137
+ settings = {k: opts[k] for k in SETTINGS if k in opts}
138
+ rate = float(req.get("rate") or 1)
139
+ if rate != 1:
140
+ if SPEED[0] <= rate <= SPEED[1]:
141
+ settings["speed"] = rate
142
+ else:
143
+ ignored.append(f"rate {req['rate']}: ElevenLabs speaks at {SPEED[0]} to {SPEED[1]}")
144
+ body = {"text": text, "model_id": model, **{k: opts[k] for k in BODY if k in opts}}
145
+ if settings:
146
+ body["voice_settings"] = settings
147
+ vid = voice_id(speaker, key)
148
+ got = _call(f"/v1/text-to-speech/{vid}/with-timestamps?output_format=pcm_{RATE}", key, json.dumps(body).encode())
149
+ pcm = base64.b64decode(got["audio_base64"])
150
+ _wav(req["out"], pcm)
151
+ timing = got.get("alignment") or {}
152
+ words = words_from_chars(timing.get("characters") or [], timing.get("character_start_times_seconds") or [],
153
+ timing.get("character_end_times_seconds") or [])
154
+ if not words or not any(w["end"] for w in words):
155
+ words = _forced(req["out"], TAG.sub("", text), key)
156
+ return {"words": words, "speaker": speaker, "version": _version(model), "seconds": round(len(pcm) / 2 / RATE, 3),
157
+ "tags": tags, "ignored": ignored}
@@ -0,0 +1,10 @@
1
+ """For KINE_VOICE_CMD_ELEVENLABS: a JSON list of requests on stdin, the list of results on stdout.
2
+
3
+ KINE_VOICE_CMD_ELEVENLABS='["/path/to/python", "-m", "kinescript_elevenlabs"]' kine voice scene.json
4
+ """
5
+ import json
6
+ import sys
7
+
8
+ from . import synth
9
+
10
+ sys.stdout.write(json.dumps([synth(r) for r in json.loads(sys.stdin.read())]))
@@ -0,0 +1,88 @@
1
+ Metadata-Version: 2.4
2
+ Name: kinescript-elevenlabs
3
+ Version: 0.1.0
4
+ Summary: ElevenLabs voices for kine voice: audio tags such as whispers, any voice in your account, and word times
5
+ Author: Dr. Know How
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/drknowhow/kinescript/tree/main/plugins/kinescript-elevenlabs
8
+ Project-URL: Documentation, https://drknowhow.github.io/kinescript/
9
+ Project-URL: Source, https://github.com/drknowhow/kinescript/tree/main/plugins/kinescript-elevenlabs
10
+ Project-URL: Issues, https://github.com/drknowhow/kinescript/issues
11
+ Project-URL: Changelog, https://github.com/drknowhow/kinescript/blob/main/CHANGELOG.md
12
+ Keywords: kinescript,elevenlabs,text to speech,tts,voice-over,audio tags,word timestamps
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
24
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
25
+ Classifier: Topic :: Multimedia :: Video
26
+ Requires-Python: >=3.10
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Dynamic: license-file
30
+
31
+ # kinescript-elevenlabs
32
+
33
+ [ElevenLabs](https://elevenlabs.io) voices for `kine voice`. It speaks the `text` of a scene's sounds through
34
+ ElevenLabs' API into WAV files and writes the time of each word, so layers can start on a word and captions follow
35
+ the voice. Eleven v4 and v3 act on audio tags such as `[whispers]`, `[laughs]` or `[sighs]`.
36
+
37
+ ```json
38
+ {"id": "vo1", "role": "voice", "backend": "elevenlabs", "speaker": "George",
39
+ "text": "[whispers] Nobody knows yet. [[go]][laughs] Render it.", "options": {"stability": 0.3}}
40
+ ```
41
+
42
+ ```bash
43
+ kine voice scene.json # writes voice/vo1.wav and voice/vo1.words.json
44
+ kine check scene.json
45
+ ```
46
+
47
+ ## Install
48
+
49
+ It needs Kinescript 1.3 or newer. It has no dependencies of its own, so it installs next to Kinescript on any
50
+ Python 3.10 or newer:
51
+
52
+ ```bash
53
+ pip install kinescript-elevenlabs
54
+ ```
55
+
56
+ From a checkout of [Kinescript](https://github.com/drknowhow/kinescript), `pip install ./plugins/kinescript-elevenlabs`
57
+ does the same.
58
+
59
+ It needs an API key from your ElevenLabs account (Developers > API keys) in `ELEVENLABS_API_KEY`. Every line it
60
+ speaks uses characters of that account's quota. `kine voice` speaks a line again only when its text, speaker, rate,
61
+ backend or options changed, so re-running it on an unchanged scene costs nothing.
62
+
63
+ ## Voices and settings
64
+
65
+ `speaker` is a voice id, or the name of a voice in your account (`George`, `Aria`); George unless the sound names one.
66
+ `rate` sets ElevenLabs' speed, which takes 0.7 to 1.2; a rate outside that is spoken at 1 and listed under
67
+ `ignored`.
68
+
69
+ `options` passes these on:
70
+
71
+ - `model`: `eleven_v4` by default. `eleven_v3` also acts on tags; other models, such as `eleven_multilingual_v2`
72
+ or `eleven_flash_v2_5`, get the text without its tags.
73
+ - `stability`, `similarity_boost`, `style`, `use_speaker_boost`: ElevenLabs' voice settings. Lower stability gives
74
+ a wider emotional range.
75
+ - `seed`, `language_code`, `apply_text_normalization`: passed to the request as they are.
76
+
77
+ An option it does not know is listed under `ignored` in what `kine voice` prints.
78
+
79
+ ## Word times
80
+
81
+ ElevenLabs returns the time of each character it says; the plugin joins them into the words of the text as written,
82
+ leaving tags out and timing each word from its first letter to its last. When a model returns no character times,
83
+ the plugin asks ElevenLabs' forced alignment for them, which is billed like speech to text.
84
+
85
+ ## Another Python
86
+
87
+ To run it from a Python other than Kinescript's, set `KINE_VOICE_CMD_ELEVENLABS` to that Python and the module:
88
+ `["/path/to/python", "-m", "kinescript_elevenlabs"]`.
@@ -0,0 +1,10 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ kinescript_elevenlabs/__init__.py
5
+ kinescript_elevenlabs/__main__.py
6
+ kinescript_elevenlabs.egg-info/PKG-INFO
7
+ kinescript_elevenlabs.egg-info/SOURCES.txt
8
+ kinescript_elevenlabs.egg-info/dependency_links.txt
9
+ kinescript_elevenlabs.egg-info/entry_points.txt
10
+ kinescript_elevenlabs.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [kinescript.voice]
2
+ elevenlabs = kinescript_elevenlabs:synth
@@ -0,0 +1 @@
1
+ kinescript_elevenlabs
@@ -0,0 +1,45 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "kinescript-elevenlabs"
7
+ version = "0.1.0"
8
+ description = "ElevenLabs voices for kine voice: audio tags such as whispers, any voice in your account, and word times"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ authors = [{ name = "Dr. Know How" }]
13
+ requires-python = ">=3.10"
14
+ dependencies = []
15
+ keywords = ["kinescript", "elevenlabs", "text to speech", "tts", "voice-over", "audio tags", "word timestamps"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Environment :: Console",
19
+ "Intended Audience :: Developers",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3 :: Only",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Programming Language :: Python :: 3.13",
27
+ "Programming Language :: Python :: 3.14",
28
+ "Topic :: Multimedia :: Sound/Audio :: Speech",
29
+ "Topic :: Multimedia :: Video",
30
+ ]
31
+
32
+ # Same rule as the main package: trusted publishing from drknowhow/kinescript marks a link verified only under
33
+ # https://github.com/drknowhow/kinescript or https://drknowhow.github.io/kinescript.
34
+ [project.urls]
35
+ Homepage = "https://github.com/drknowhow/kinescript/tree/main/plugins/kinescript-elevenlabs"
36
+ Documentation = "https://drknowhow.github.io/kinescript/"
37
+ Source = "https://github.com/drknowhow/kinescript/tree/main/plugins/kinescript-elevenlabs"
38
+ Issues = "https://github.com/drknowhow/kinescript/issues"
39
+ Changelog = "https://github.com/drknowhow/kinescript/blob/main/CHANGELOG.md"
40
+
41
+ [project.entry-points."kinescript.voice"]
42
+ elevenlabs = "kinescript_elevenlabs:synth"
43
+
44
+ [tool.setuptools]
45
+ packages = ["kinescript_elevenlabs"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+