Skip to content

Commit fa5a036

Browse files
committed
attempting revision3 release
1 parent 9007a0d commit fa5a036

4 files changed

Lines changed: 40 additions & 14 deletions

File tree

.github/workflows/build.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ jobs:
4242
cd ..
4343
- uses: ghalactic/github-release-from-tag@v5
4444
with:
45-
draft: "true"
4645
checksumGenerateAssets: "false"
4746
assets: |
4847
- path: STAR_win64.zip

readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Pretty much this entire project is written in python sans a couple of providers
2626
1. After opening a terminal window up to this repository's directory, create a python virtual environment to make an isolated workspace for all modules this project uses: `python -m venv venv`
2727
2. Activate the virtual environment you just created: on windows `venv\scripts\activate`, on MacOS `source venv/bin/activate`, or on Linux `venv/bin/activate`
2828
3. Install requirements: `pip install -r requirements.txt`
29-
4. If you wish to run the balcony provider, you'll want to download [balcon.zip](https://www.cross-plus-a.com/balcon.zip) and place the contained balcon.exe in the provider directory. As of Dec 09 2024 an update to balcon causes an extra charset detection dll to be required, so if you want you can use the [balcon.exe used in STAR's CI actions](https://samtupy.com/star_ci/balcon.exe) instead.
29+
4. If you wish to run the balcony provider, you'll want to download [balcon.zip](https://www.cross-plus-a.com/balcon.zip) and place the contained balcon.exe in the provider directory. As of Dec 09 2024 an update to balcon causes an extra charset detection component (chsdet.dll) to also be required, so if you want to avoid that you can use the [balcon.exe used in STAR's CI actions](https://samtupy.com/star_ci/balcon.exe) instead. WARNING! If you place libsamplerate.dll from the balcon distrobution alongside balcon.exe, balcon's `{{Audio=path}}` tag will begin working, meaning that anyone sharing their voice might also be sharing any audio file on their system that somebody knows the path to (a HUGE security risk)! Only put this DLL in place for local setups or hwen you are absolutely sure everyone on your network can be trusted. The dll is not included in the public STAR distrobution.
3030
5. If you want to use the sammy provider, you need the sam.exe synthesizer. You can just download the one the build workflow uses [from here](https://samtupy.com/star_ci/sam.exe) if you like, or else I built that from [this repository](https://github.com/s-macke/SAM) with the SConstruct line `Program("sam", Glob("src/*.c"), CPPFLAGS = ["/Os"])` if you'd rather build it yourself. Regardless, you'll want to place sam.exe in the provider folder.
3131

3232
From this point you can cd to the coagulator directory and run coagulator.py, cd to the provider directory and run balcony.py or macsay.py, or cd to the user directory and run STAR.py based on what you want to do. You'll likely want to configure the coagulator/provider first, and so everything accept the user client supports a --configure command line argument which brings up a configuration interface, and/or --config filename.ini to load configuration from a specified path (useful for things like unix daemons).

user/STAR.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ def resume(self):
5757
def playing(self): return self.handle.is_playing if self.handle else None
5858
def wait_for_finish(self):
5959
#Todo: Convert to bass sync when possible.
60-
while self.finish_func and self.handle and (self.handle.is_playing or self.handle.is_paused): time.sleep(0.005)
60+
try:
61+
while self.finish_func and self.handle and (self.handle.is_playing or self.handle.is_paused): time.sleep(0.005)
62+
except BassError: return
6163
if self.handle: self.finish_func(self)
6264

6365
def is_valid_ws_uri(uri):
@@ -160,23 +162,30 @@ def __init__(self, data = None):
160162
self.data = data
161163

162164
class star_local:
163-
"""This class facilitates a convenient local STAR stack for cases when no remote servers are available. When created the coagulator and some providers are run, and when destroyed the child processes are terminated."""
165+
"""This class facilitates a convenient local STAR stack for cases when no remote servers are available. When the start method is called the coagulator and some providers are run, and when stop is called or the object is destroyed the child processes are terminated."""
164166
def __init__(self, client):
165167
self.client = client
166168
self.abort = threading.Event()
167169
self.processes = [["coagulator", [sys.executable, "../coagulator/coagulator.py", "--authless"] if not hasattr(sys, "frozen") else ["coagulator", "--authless"], None]]
168170
provider = "balcony" if sys.platform == "win32" else "macsay" if sys.platform == "darwin" else None
169171
if provider: self.processes.append([f"{provider} provider", [sys.executable, os.path.join("..", "provider", provider + ".py"), "--hosts", "ws://127.0.0.1:7774"] if not hasattr(sys, "frozen") else [provider, "--hosts", "ws://127.0.0.1:7774"], None])
170172
if sys.platform == "win32": self.processes.append(["sammy provider", [sys.executable, os.path.join("..", "provider", "sammy.py"), "--hosts", "ws://127.0.0.1:7774"] if not hasattr(sys, "frozen") else ["sammy", "--hosts", "ws://127.0.0.1:7774"], None])
171-
self.start()
172173
def __del__(self): self.stop()
173174
def start(self, silent = False):
174175
self.abort.clear()
175176
for p in self.processes:
176-
p[2] = subprocess.Popen(p[1], creationflags = subprocess.CREATE_NO_WINDOW if sys.platform == "win32" else 0)
177+
try: p[2] = subprocess.Popen(p[1], creationflags = subprocess.CREATE_NO_WINDOW if sys.platform == "win32" else 0)
178+
except Exception as e: return self.fail(f"Unable to start {p[0]}, {e}")
177179
threading.Thread(target = self.monitor, daemon = True).start()
178180
atexit.register(self.stop)
179181
return True
182+
def fail(self, message):
183+
wx.CallAfter(wx.MessageDialog(self.client, message, "Local STAR setup Error", wx.OK).ShowModal)
184+
wx.CallAfter(self.client.Close)
185+
self.stop()
186+
config["host"] = ""
187+
config.write() # insure the user doesn't get stuck in a loop of coagulation setup errors.
188+
return False
180189
def monitor(self):
181190
while not self.abort.wait(1):
182191
for p in self.processes:
@@ -367,16 +376,22 @@ def __init__(self, parent = None):
367376
if "host" in config and config["host"] != "" and not self.configuration.validate():
368377
r = self.on_options()
369378
if not r: return wx.Exit()
370-
self.check_local()
371-
self.connection_thread = threading.Thread(target = self.connect, args = [config.get("host", "") if not self.local else "ws://127.0.0.1:7774"], daemon = True)
372-
self.connection_thread.start()
379+
if self.check_local():
380+
self.connection_thread = threading.Thread(target = self.connect, args = [config.get("host", "") if not self.local else "ws://127.0.0.1:7774"], daemon = True)
381+
self.connection_thread.start()
382+
else: self.connection_thread = None
373383
def check_local(self):
374-
"""If the host is 'local', set up a star_local object. Otherwise, destroy it thus terminating the child coagulator and providers."""
375-
if config.get("host", "") == "local": self.local = star_local(self)
384+
"""If the host is 'local', set up a star_local object. Otherwise, destroy it thus terminating the child coagulator and providers. Returns false if the connection thread should not be started because the local stack failed to be set up."""
385+
if config.get("host", "") == "local":
386+
self.local = star_local(self)
387+
if not self.local.start():
388+
self.local = None
389+
return False
376390
else:
377391
if hasattr(self, "local") and self.local: self.local.stop()
378392
self.local = None
379393
self.run_local_btn.Enabled = config.get("host", "") != "local"
394+
return True
380395
def on_copy_voicename(self, evt):
381396
"""Copies the currently focused voice name to the clipboard, called when ctrl+c is pressed on a voice name in the voices list."""
382397
voice = self.voices_list.FocusedItem
@@ -601,7 +616,6 @@ def reconnect(self, label = "Connecting...", full = True):
601616
self.connection_thread.join()
602617
self.connection_thread = None
603618
self.initial_connection = False
604-
self.check_local()
605619
self.speech_requests = {}
606620
self.speech_requests_text = {}
607621
self.voices = {}
@@ -611,7 +625,7 @@ def reconnect(self, label = "Connecting...", full = True):
611625
self.connecting_panel.Show()
612626
if label_change: self.connecting_label.SetFocus()
613627
self.main_panel.Hide()
614-
if full:
628+
if full and self.check_local():
615629
self.connection_thread = threading.Thread(target = self.connect, args = [config.get("host", "") if not self.local else "ws://127.0.0.1:7774"], daemon = True)
616630
self.connection_thread.start()
617631
def connect(self, host):

user/readme.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,17 @@ The next great feature supported in these scripts is voice aliases or character
9292

9393
The above example shows the usage of comments to denote the characters from the scenes, and shows how by defining the character alias rs5 for example, we can then avoid needing to type RoboSoft Five over and over again in the script which can be a huge speed boost. Any whitespace is trimmed from the aliases so that space between the equals sign is optional, and an alias defined anywhere in your script will effect the entire document E. you can safely place your aliases at the bottom of your script if you like. Aliases can include default rate and pitch parameters, such as `|MadMike = Microsoft Mike<p=9 r=3>` for example. If a script line then contains any parameters, that line will override the defaults in the voice alias.
9494

95+
### Balabolka / balcon tags
96+
Though they will not be fully explained here as Balabolka provides it's own documentation, it is worth noting that it is possible to use the typical voice tags supported by the Balabolka program, with the exception of the {{Audio=}} tag. For example,
97+
98+
`Sam: Hi there, that's cool! {{Voice=mary}} yeah it really is!`
99+
100+
Would cause the voice to switch from Sam to mary half way through synthesis.
101+
102+
If you really want to get the {{Audio=}} tag working with the balcony provider, you must [download balcon.zip](https://www.cross-plus-a.com/balcon.zip) and place the libsamplerate.dll file alongside balcon.exe. Be sure you really want to do this though particularly if you want to share voices with others, as it provides access to any audio file on your system given a path! For example, if the audio tag is enabled, the following line would embed the specified sounds into the generated stream.
103+
104+
`Sam: Hi there, {{Audio=C:\Windows\Media\Chord.wav}} that's cool! {{Voice=mary}} yeah it really is! {{Audio=C:\windows\media\notify.wav}}`
105+
95106
### Selective rendering
96107
The final supported feature in the script format allows for selective rendering. Often, it might happen that you might want to simply tweak one or 2 lines, or continuously add new voice clips to your audio production as you are sound designing. While you could just paste only the part of your script in the field you wish to render, this would mess up any counters which would allow you to account for what order the voice clips should play in. Instead, you can wrap groups of lines in `< and >` characters to select only the lines contained within to render, like this.
97108

@@ -128,7 +139,7 @@ You can then run balcony.exe or sam.exe standalone and the voices will be shared
128139
## Change log
129140
### Revision 3
130141
This is a major update to STAR which includes a complete user client rewrite and consequently the introduction of several useful features.
131-
* The user client was completely rewritten from scratch in python and WX Widgets, meaning that though feedback must still be gathered to make it look right, the user client can now be used without a screen reader!
142+
* The user client was completely rewritten from scratch in python and WX Widgets, meaning that though feedback must still be gathered to make it look right or even to insure that controls are visible at all, the user client should soon be able to be used without a screen reader within a couple of revisions!
132143
* Due to the script text field being a true richtext control, the previewing hotkeys were changed to control+alt+up, down, and space rather than just control. This was forced on us because NVDA at least seems to always speak when control+up and down are pressed on a text field regardless of any application code.
133144
* It is now possible to press ctrl+alt+enter on any valid speech line in the script to begin auto previewing the entire script up to it's end or the next error.
134145
* You can press alt+backspace anywhere in the main screen to pause and resume any playing speech, thus the stop currently playing speech button was removed from the interface.
@@ -137,7 +148,9 @@ This is a major update to STAR which includes a complete user client rewrite and
137148
* Now that the options dialog exists, the output device list has been moved to that dialog.
138149
* It is now possible to consolidate the entire script into one audio file! Next to the script field, there is an output subdirectory or consolidated filename field. If you set thhis to a filename such as output.wav instead of a folder name such as output, now a single output.wav file will be created containing all voice clips seperated by a configurable amount of silence.
139150
* The synthesis caching is much improved. Now if you preview a script before rendering it, the render will be almost instant as the cached phrases from the synthesis will now be used while rendering. It is also possible to manually clear the audio cache in the options dialog.
151+
* The render progress sound was removed in favor of a real native progress bar. It sounds a bit less cool but should be visually accessible soon and is far less expensive than playing the sound.
140152
* There are some cool new features in the script syntax, such as selecting only certain lines to render on the minor end to being able to define character aliases per script on the very useful end!
153+
* Typically STAR coagulators now require authentication. To make dealing with this easier, STAR can now save previous hosts you connect to, allowing you to select between them in the options dialog.
141154
* Full documentation is now provided as well as automatic windows client builds on Github.
142155

143156
## Disclaimer

0 commit comments

Comments
 (0)