Running as a service: Windows, Linux, macOS
Installing the services as system services so they start without anyone signing in: Windows, Linux (systemd), macOS (LaunchDaemon, LaunchAgent).
The daily launcher starts the services in their own windows, under the signed-in user. On a machine acting as a server it is better to run them as system services: they start with the machine, without anyone signing in, the system restarts them after a failure, and they write their logs into their own folders. This chapter describes the installation on Windows, Linux and macOS.
When it is worth it
- As a service: when the machine is a server – other machines' LiveCaption uses it, and it must run even when nobody is signed in.
- With the daily launcher: when you work on the same machine the services run on, and it is enough for them to run while you work (see Daily start and stop).
The two modes do not mix for one service on one machine: the daily launcher does not start a console twin next to an installed service, nor does it stop it – it prints the service manager's command instead.
The common rules
- The installer is the service's own launcher, with the
-InstallServiceswitch. The same command also updates: run it again after installing a newer version. Removal is-UninstallService; the data root (including the log) is only deleted with the-RemoveDataswitch. - One instance per service per machine can be installed.
- The order is fixed here too: first the account service, then the translator and the voice service, finally the caption service. The caption service waits for the translator and the voice service registered on the machine before it measures the video memory.
- The account service's address is mandatory (
-AccountUrl), and the service needs a peer token (the service's secret for fetching the authorization snapshot). The installer takes the peer token from the environment variable of the user running the installation and moves it into the service's protected secrets folder. So before installing, run theAccountServer\setup-account-peerstool with the-Tokensswitch (see Keys and permissions for clients). - No secret goes into the service entry: the entry only holds the path of the secret file, which only the service account and the administrator can read.
- No initial administrator is created when running as a service – see below.
The service manager decides by how the service exited:
| Exit | What the system does |
|---|---|
| normal stop (exit code 0) | does not restart it |
| usage error, for example a wrong switch (exit code 1) | does not restart it – the error has to be fixed |
| runtime failure (exit code 4) or a crash | restarts it after 60 seconds |
Windows
From an elevated (administrator) PowerShell window. The installer does not publish: if the service's package is out of date, refresh it first in a non-elevated window (-Rebuild).
.\AccountServer\start-accountserver.ps1 -InstallService -CreateAdmin admin
.\TranslatorServer\start-translatorserver.ps1 -InstallService -AccountUrl http://127.0.0.1:8100
.\VoiceServer\start-voiceserver.ps1 -InstallService -AccountUrl http://127.0.0.1:8100 -AcceptXttsLicense
.\CaptionServer\start-captionserver.ps1 -InstallService -Gpu cuda13 -GpuReserve 6144 -AccountUrl http://127.0.0.1:8100
- The services are named
LiveCaptionPro.<Service>(for exampleLiveCaptionPro.CaptionServer), each running under its own virtual account. The program lives in%ProgramFiles%\LiveCaptionPro\<service>, the data root and the log in%ProgramData%\LiveCaptionPro\<service>. - The models go into shared folders (
%ProgramData%\LiveCaptionPro\models,hf,tts): the installer copies the models already on the machine there (-ModelsFrom). - The services are also visible in the Windows Services console (
services.msc), where they can be started and stopped.
Linux
It needs systemd and root rights:
sudo pwsh AccountServer/start-accountserver.ps1 -InstallService
sudo pwsh TranslatorServer/start-translatorserver.ps1 -InstallService -AccountUrl http://127.0.0.1:8100
sudo pwsh VoiceServer/start-voiceserver.ps1 -InstallService -AccountUrl http://127.0.0.1:8100
sudo pwsh CaptionServer/start-captionserver.ps1 -InstallService -Gpu cuda13 -GpuReserve 6144 -AccountUrl http://127.0.0.1:8100
- The units are named
live-caption-pro-<service>.service, the user islive-caption-pro. The program lives in/opt/live-caption-pro/<service>, the data root under/var/lib/live-caption-pro/<service>; systemd hands over the secrets from/etc/live-caption-pro/credentials/, which only root can read. - Manage them with the usual command:
sudo systemctl status|start|stop live-caption-pro-captionserver. The log also appears in the journal:journalctl -u live-caption-pro-captionserver. systemctl startwaits until the service is actually serving – for the caption service this can take a minute or two because of the video memory measurement.
macOS: LaunchDaemon, starting with the machine
A LaunchDaemon is a system-level background job on macOS: it starts with the machine, without anyone signing in. It needs root rights, with sudo -H (without -H, root would write into your own home folder):
sudo -H pwsh AccountServer/start-accountserver.ps1 -InstallService -DbEnv LCP_DB_<NAME>
sudo -H pwsh TranslatorServer/start-translatorserver.ps1 -InstallService -AccountUrl http://127.0.0.1:8100
sudo -H pwsh VoiceServer/start-voiceserver.ps1 -InstallService -AccountUrl http://127.0.0.1:8100
sudo -H pwsh CaptionServer/start-captionserver.ps1 -InstallService -GpuReserve 6144 -AccountUrl http://127.0.0.1:8100
- The jobs are labelled
pro.livecaption.<service>, their descriptors sit in/Library/LaunchDaemons. Each runs under its own system user (for example_lcp_captionserver), so no service can read another one's secret. - The program lives in
/Library/LiveCaptionPro/<service>, the data root in/Library/Application Support/LiveCaptionPro/<service>, the log in/Library/Logs/LiveCaptionPro/<service>. - Stop:
sudo launchctl bootout system/pro.livecaption.captionserver; start:sudo launchctl bootstrap system /Library/LaunchDaemons/pro.livecaption.captionserver.plist; status:launchctl print system/pro.livecaption.captionserver. A job stopped from outside (for example withkill) is restarted by the system –bootoutis the way to stop it for good. - The installer allows the program in the macOS application firewall if the firewall is on, and warns if the machine is set to sleep.
- The account service's database: starting without a sign-in needs a PostgreSQL running off the machine (on the network) or at system level; a database in Docker Desktop or under the user's
brew servicesonly lives after a sign-in.
macOS: LaunchAgent, the per-user variant
A LaunchAgent is a background job of the signed-in user: it starts at sign-in and stops at sign-out. It is installed without root rights, from your own terminal window, with the -ServiceScope User switch. -Port is mandatory and cannot be any service's default port; the recommended choice is the default port + 10000:
pwsh AccountServer/start-accountserver.ps1 -InstallService -ServiceScope User -Port 18100 -DbEnv LCP_DB_<NAME>
pwsh TranslatorServer/start-translatorserver.ps1 -InstallService -ServiceScope User -Port 18080 -AccountUrl http://127.0.0.1:18100
pwsh VoiceServer/start-voiceserver.ps1 -InstallService -ServiceScope User -Port 18090 -AccountUrl http://127.0.0.1:18100
pwsh CaptionServer/start-captionserver.ps1 -InstallService -ServiceScope User -Port 15111 -GpuReserve 6144 -AccountUrl http://127.0.0.1:18100
- The descriptor is
~/Library/LaunchAgents/pro.livecaption.<service>.plist, the program lives in~/Library/LiveCaptionPro/<service>, the data root in~/Library/Application Support/LiveCaptionPro-Service/<service>, the log in~/Library/Logs/LiveCaptionPro/<service>. - The web interface port is the given port + 1 (18101 for the account service in the example).
- It reads the models from the user's own model folders, without copying.
- Control without
sudo:launchctl bootout gui/$(id -u)/pro.livecaption.captionserverstops it (the next sign-in restarts it;launchctl disableturns it off for good), andlaunchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/pro.livecaption.captionserver.pliststarts it. - The firewall needs root, so with the firewall on, the installer only prints the manual command (
sudo …/socketfilterfw) that has to be run for network access. After removal, the entry has to be taken off by hand the same way.
Which macOS variant to choose
| Aspect | LaunchDaemon | LaunchAgent |
|---|---|---|
| when it starts | with the machine, without a sign-in | when the user signs in |
| root rights | required (sudo -H) |
not allowed |
| who runs it | a separate system account per service | the installing user |
| ports | the default ports | a different, mandatory -Port |
| firewall | allowed by the installer | manual command |
| who it is for | a machine acting as a server | someone who wants supervised services in their own session, without root |
The same service cannot be both a daemon and an agent: remove one variant before installing the other. Since macOS 15, a program can only reach other machines on the local network with the Local Network permission (System Settings → Privacy & Security → Local Network); if a service cannot reach the network database or the other machine, check this first.
What differs per service
| Service | What applies only to it |
|---|---|
| account service | the database binding (the name of the environment variable holding the connection string) comes from -DbEnv, otherwise from the default binding; there is no dependency entry on PostgreSQL: if the database is unreachable for 60 seconds, the service exits and the system retries a minute later |
| translator | the installer copies the machine's entire Hugging Face cache into the shared folder – this can be hundreds of GB; it prints the size before copying and stops if space is short. A narrowed source: -ModelsFrom <folder>, skipping it: -ModelsFrom none |
| voice service | needs a machine-wide Python 3.10–3.12 (one installed in a user profile cannot be reached by the service account); it only downloads the model with the -AcceptXttsLicense switch |
| caption service | -GpuReserve is mandatory (in MiB or as %): this much video memory is left free for the other services |
The initial administrator when running as a service
Running as a service, the account service does not create an initial administrator, because it would have nowhere to show the password. If the database has no administrator able to sign in yet:
- on Windows, the
-CreateAdmin <name>switch adds one at the end of the installation and reads the password from the keyboard; - on Linux and macOS, the installer prints the three maintenance commands at the end (add the user, the Administrator role, the password); run them after the installation from your own, non-
sudowindow.
If the services already ran from the console with the same database, the existing administrator stays and there is nothing to do.