tuxcast 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.
Files changed (56) hide show
  1. tuxcast-0.1.0/.gitignore +21 -0
  2. tuxcast-0.1.0/CHANGELOG.md +36 -0
  3. tuxcast-0.1.0/LICENSE +21 -0
  4. tuxcast-0.1.0/PKG-INFO +163 -0
  5. tuxcast-0.1.0/README.md +136 -0
  6. tuxcast-0.1.0/contrib/README.md +11 -0
  7. tuxcast-0.1.0/contrib/patches/twitch-oauth-port.toml +18 -0
  8. tuxcast-0.1.0/contrib/udev/70-streamdeck.rules +6 -0
  9. tuxcast-0.1.0/pyproject.toml +66 -0
  10. tuxcast-0.1.0/src/tuxcast/__init__.py +3 -0
  11. tuxcast-0.1.0/src/tuxcast/__main__.py +3 -0
  12. tuxcast-0.1.0/src/tuxcast/audio.py +211 -0
  13. tuxcast-0.1.0/src/tuxcast/bridge.py +186 -0
  14. tuxcast-0.1.0/src/tuxcast/cli.py +456 -0
  15. tuxcast-0.1.0/src/tuxcast/convert/__init__.py +286 -0
  16. tuxcast-0.1.0/src/tuxcast/convert/actions.py +284 -0
  17. tuxcast-0.1.0/src/tuxcast/convert/elgato.py +326 -0
  18. tuxcast-0.1.0/src/tuxcast/convert/keymap.py +66 -0
  19. tuxcast-0.1.0/src/tuxcast/dashboard/__init__.py +464 -0
  20. tuxcast-0.1.0/src/tuxcast/dashboard/static/app.css +275 -0
  21. tuxcast-0.1.0/src/tuxcast/dashboard/static/app.js +508 -0
  22. tuxcast-0.1.0/src/tuxcast/dashboard/static/fonts/Barlow-Bold.woff2 +0 -0
  23. tuxcast-0.1.0/src/tuxcast/dashboard/static/fonts/Barlow-Medium.woff2 +0 -0
  24. tuxcast-0.1.0/src/tuxcast/dashboard/static/fonts/Barlow-Regular.woff2 +0 -0
  25. tuxcast-0.1.0/src/tuxcast/dashboard/static/fonts/Barlow-SemiBold.woff2 +0 -0
  26. tuxcast-0.1.0/src/tuxcast/dashboard/static/fonts/BarlowCondensed-Bold.woff2 +0 -0
  27. tuxcast-0.1.0/src/tuxcast/dashboard/static/fonts/BarlowCondensed-SemiBold.woff2 +0 -0
  28. tuxcast-0.1.0/src/tuxcast/dashboard/static/fonts/OFL.txt +93 -0
  29. tuxcast-0.1.0/src/tuxcast/dashboard/static/index.html +48 -0
  30. tuxcast-0.1.0/src/tuxcast/dashboard/static/logo.svg +21 -0
  31. tuxcast-0.1.0/src/tuxcast/deck.py +110 -0
  32. tuxcast-0.1.0/src/tuxcast/doctor/__init__.py +111 -0
  33. tuxcast-0.1.0/src/tuxcast/doctor/audio.py +45 -0
  34. tuxcast-0.1.0/src/tuxcast/doctor/discord.py +67 -0
  35. tuxcast-0.1.0/src/tuxcast/doctor/display.py +41 -0
  36. tuxcast-0.1.0/src/tuxcast/doctor/encoders.py +77 -0
  37. tuxcast-0.1.0/src/tuxcast/doctor/network.py +62 -0
  38. tuxcast-0.1.0/src/tuxcast/doctor/obs.py +69 -0
  39. tuxcast-0.1.0/src/tuxcast/doctor/spotify.py +62 -0
  40. tuxcast-0.1.0/src/tuxcast/doctor/streamdeck.py +46 -0
  41. tuxcast-0.1.0/src/tuxcast/patch.py +145 -0
  42. tuxcast-0.1.0/src/tuxcast/paths.py +40 -0
  43. tuxcast-0.1.0/src/tuxcast/streamcontroller.py +68 -0
  44. tuxcast-0.1.0/src/tuxcast/system.py +105 -0
  45. tuxcast-0.1.0/src/tuxcast/systemd.py +65 -0
  46. tuxcast-0.1.0/src/tuxcast/ui.py +77 -0
  47. tuxcast-0.1.0/tests/__init__.py +0 -0
  48. tuxcast-0.1.0/tests/conftest.py +113 -0
  49. tuxcast-0.1.0/tests/test_audio.py +58 -0
  50. tuxcast-0.1.0/tests/test_bridge.py +54 -0
  51. tuxcast-0.1.0/tests/test_cli.py +80 -0
  52. tuxcast-0.1.0/tests/test_convert.py +309 -0
  53. tuxcast-0.1.0/tests/test_dashboard.py +161 -0
  54. tuxcast-0.1.0/tests/test_doctor.py +114 -0
  55. tuxcast-0.1.0/tests/test_keymap.py +32 -0
  56. tuxcast-0.1.0/tests/test_patch.py +97 -0
@@ -0,0 +1,21 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .venv/
6
+ build/
7
+ dist/
8
+ .pytest_cache/
9
+ .ruff_cache/
10
+ .coverage
11
+ htmlcov/
12
+
13
+ # Docs
14
+ site/
15
+
16
+ # Editors
17
+ .idea/
18
+ .vscode/
19
+ *.swp
20
+ wiki/
21
+ docs/demo/
@@ -0,0 +1,36 @@
1
+ # Changelog
2
+
3
+ All notable changes to tuxcast are listed here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and tuxcast uses
5
+ [semantic versioning](https://semver.org/).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.1.0] - 2026-10-08
10
+
11
+ The first release: the problems every Linux streamer hits, each solved by one command.
12
+
13
+ ### Added
14
+
15
+ - `tuxcast ui` opens a control desk for everything below: a go-live tally, the Stream Deck with
16
+ StreamController's real pages and a key-by-key preview of dropped Elgato profiles, the doctor's
17
+ checks with one-click fixes, an audio mixer with faders, mute and drag-and-drop app routing, the
18
+ Discord bridge and patches. It listens on 127.0.0.1 only and requires the token it prints. The
19
+ website has a live demo of it.
20
+ - `tuxcast doctor` checks a streaming setup in eight areas (display server, audio, GPU
21
+ encoding, OBS, Stream Deck, Discord, Spotify, network) and prints the fix for each
22
+ problem. `--json` for scripts, `--only` to focus on some areas.
23
+ - `tuxcast convert` turns Elgato Stream Deck profiles (`.streamDeckProfile`, backups and
24
+ `.sdProfile` folders, versions 1 and 2) into StreamController pages: images, titles,
25
+ folders, multi actions, hotkeys translated for AZERTY and QWERTZ keyboards, OBS,
26
+ Discord and Twitch actions. A report lists the keys to redo by hand.
27
+ - `tuxcast bridge discord` exposes Discord's IPC socket installed as a snap, Vesktop or a
28
+ native package to Flatpak clients such as StreamController, with an optional login service.
29
+ - `tuxcast audio` creates separate PipeWire sinks (game, music, voice, alerts) and routes
30
+ apps to them, so each part of the mix is its own OBS source.
31
+ - `tuxcast deck` lists Stream Decks, prints the udev rule they need, and resets a deck stuck
32
+ after a crash without unplugging it.
33
+ - `tuxcast patch` re-applies local edits that app updates wipe, through a systemd path unit.
34
+
35
+ [Unreleased]: https://github.com/achedon12/tuxcast/compare/v0.1.0...HEAD
36
+ [0.1.0]: https://github.com/achedon12/tuxcast/releases/tag/v0.1.0
tuxcast-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 achedon12
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.
tuxcast-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,163 @@
1
+ Metadata-Version: 2.5
2
+ Name: tuxcast
3
+ Version: 0.1.0
4
+ Summary: The toolkit for streaming on Linux: diagnose your setup, convert Elgato Stream Deck profiles, bridge sandboxed apps and split your audio.
5
+ Project-URL: Homepage, https://achedon12.github.io/tuxcast/
6
+ Project-URL: Documentation, https://achedon12.github.io/tuxcast/
7
+ Project-URL: Repository, https://github.com/achedon12/tuxcast
8
+ Project-URL: Issues, https://github.com/achedon12/tuxcast/issues
9
+ Project-URL: Changelog, https://github.com/achedon12/tuxcast/blob/main/CHANGELOG.md
10
+ Author: achedon12
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: discord,flatpak,linux,obs,pipewire,stream-deck,streamcontroller,streaming,twitch
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Environment :: Console
16
+ Classifier: Intended Audience :: End Users/Desktop
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Topic :: Multimedia :: Video :: Capture
24
+ Classifier: Topic :: Utilities
25
+ Requires-Python: >=3.11
26
+ Description-Content-Type: text/markdown
27
+
28
+ <p align="center">
29
+ <img src=".github/assets/banner.svg" alt="tuxcast: the toolkit for streaming on Linux" width="100%">
30
+ </p>
31
+
32
+ <p align="center">
33
+ <a href="https://github.com/achedon12/tuxcast/actions/workflows/ci.yml"><img src="https://github.com/achedon12/tuxcast/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
34
+ <a href="https://github.com/achedon12/tuxcast/releases"><img src="https://img.shields.io/github/v/release/achedon12/tuxcast?color=8b5cf6&label=release" alt="Latest release"></a>
35
+ <img src="https://img.shields.io/badge/python-3.11%2B-3776ab" alt="Python 3.11+">
36
+ <img src="https://img.shields.io/badge/dependencies-0-22c55e" alt="Zero dependencies">
37
+ <img src="https://img.shields.io/badge/root-not%20needed-22c55e" alt="No root needed">
38
+ <a href="LICENSE"><img src="https://img.shields.io/github/license/achedon12/tuxcast?color=blue" alt="MIT license"></a>
39
+ <a href="https://achedon12.github.io/tuxcast/"><img src="https://img.shields.io/badge/docs-website-8b5cf6" alt="Documentation"></a>
40
+ </p>
41
+
42
+ <p align="center">
43
+ <b>English</b> · <a href="README.fr.md">Français</a>
44
+ </p>
45
+
46
+ **tuxcast** finds what will break your stream before you go live, then fixes it. It converts
47
+ your Elgato Stream Deck profiles, connects the apps Flatpak and snap keep apart, and splits
48
+ your audio so every source gets its own fader. One command each, no root, no dependencies.
49
+
50
+ ```sh
51
+ pipx install git+https://github.com/achedon12/tuxcast.git
52
+ tuxcast doctor
53
+ ```
54
+
55
+ <p align="center">
56
+ <a href="https://achedon12.github.io/tuxcast/#intro">
57
+ <img src=".github/assets/intro-poster.jpg" alt="Watch tuxcast in 22 seconds" width="720"><br>
58
+ <sub>▶ Watch tuxcast in 22 seconds</sub>
59
+ </a>
60
+ </p>
61
+
62
+ <p align="center">
63
+ <img src=".github/assets/terminal-doctor.svg" alt="tuxcast doctor checking a Stream Deck, Discord, Spotify and the network" width="820">
64
+ </p>
65
+
66
+ ## Why
67
+
68
+ Streaming on Linux works well, until it doesn't, and it always breaks in the same places:
69
+
70
+ - 🎛️ **Your Stream Deck.** Elgato's app does not exist for Linux, and your 8 pages of keys need rebuilding by hand.
71
+ - 🔇 **Discord keys that do nothing.** Your Stream Deck app is a Flatpak, Discord is a snap, and neither can see the other.
72
+ - ⏯️ **Media buttons that do nothing either.** The Spotify snap ignores remote control.
73
+ - 🎚️ **One audio mix.** You can't keep the music out of your VODs or lower Discord alone.
74
+ - 📶 **"Unstable bitrate."** Twitch blames your connection and your speed test says it's fine (it's the Wi-Fi).
75
+
76
+ Each of these has a fix buried in a forum thread. tuxcast checks for all of them and applies the fixes.
77
+
78
+ ## What it does
79
+
80
+ | Command | |
81
+ | --- | --- |
82
+ | [`tuxcast ui`](https://achedon12.github.io/tuxcast/commands/ui/) | Opens a control desk for everything below: a go-live tally, your Stream Deck and its pages, a mixer with faders, one-click fixes ([live demo](https://achedon12.github.io/tuxcast/demo/index.html)) |
83
+ | [`tuxcast doctor`](https://achedon12.github.io/tuxcast/commands/doctor/) | Checks display server, audio, GPU encoder, OBS, Stream Deck, Discord, Spotify and network. Each problem comes with its fix |
84
+ | [`tuxcast convert`](https://achedon12.github.io/tuxcast/commands/convert/) | Turns Elgato `.streamDeckProfile` exports into [StreamController](https://streamcontroller.core447.com/) pages: images, folders, multi actions, hotkeys (AZERTY and QWERTZ aware), OBS, Discord and Twitch keys |
85
+ | [`tuxcast bridge discord`](https://achedon12.github.io/tuxcast/commands/bridge/) | Exposes Discord's socket (snap, Vesktop, native) to Flatpak clients, and recreates the bridge at every login |
86
+ | [`tuxcast audio`](https://achedon12.github.io/tuxcast/commands/audio/) | Separate PipeWire sinks for game, music, voice and alerts, and routes apps to them |
87
+ | [`tuxcast deck`](https://achedon12.github.io/tuxcast/commands/deck/) | Lists Stream Decks, prints the udev rule they need, and resets one that froze after a crash, without unplugging it |
88
+ | [`tuxcast patch`](https://achedon12.github.io/tuxcast/commands/patch/) | Re-applies the fixes you made to app files every time an update wipes them |
89
+
90
+ ### Or run it from a control desk
91
+
92
+ `tuxcast ui` opens a dashboard on your machine: a tally that tells you whether you can go live, your
93
+ Stream Deck with its real pages, a mixer with a fader per audio channel, and a button for every fix.
94
+ [Try the live demo](https://achedon12.github.io/tuxcast/demo/index.html), no install needed.
95
+
96
+ <p align="center">
97
+ <a href="https://achedon12.github.io/tuxcast/demo/index.html">
98
+ <img src="docs/assets/ui-desk.png" alt="The tuxcast dashboard: the tally, a Stream Deck with its pages, the checks and the audio mixer" width="900">
99
+ </a>
100
+ </p>
101
+
102
+ ### Bring your Stream Deck profiles from Windows
103
+
104
+ <p align="center">
105
+ <img src=".github/assets/terminal-convert.svg" alt="tuxcast convert turning an Elgato profile into StreamController pages" width="760">
106
+ </p>
107
+
108
+ ## Install
109
+
110
+ You need Python 3.11 or newer, which every current distribution ships.
111
+
112
+ ```sh
113
+ pipx install git+https://github.com/achedon12/tuxcast.git
114
+ ```
115
+
116
+ or `uv tool install git+https://github.com/achedon12/tuxcast.git`, or the
117
+ [installer script](install.sh) (`curl -fsSL https://raw.githubusercontent.com/achedon12/tuxcast/main/install.sh | sh`).
118
+ Then start with `tuxcast doctor`.
119
+
120
+ ## Guides
121
+
122
+ The [website](https://achedon12.github.io/tuxcast/) (also in the [wiki](https://github.com/achedon12/tuxcast/wiki))
123
+ has a guide for each part of a Linux streaming setup, with the manual steps for people who
124
+ prefer to do it by hand:
125
+
126
+ [Streaming on Linux in 2026](https://achedon12.github.io/tuxcast/guides/streaming-on-linux/) ·
127
+ [OBS on Linux](https://achedon12.github.io/tuxcast/guides/obs/) ·
128
+ [Stream Deck on Linux](https://achedon12.github.io/tuxcast/guides/stream-deck/) ·
129
+ [Audio routing](https://achedon12.github.io/tuxcast/guides/audio/) ·
130
+ [Discord and Spotify in sandboxes](https://achedon12.github.io/tuxcast/guides/sandboxes/) ·
131
+ [Music without claims](https://achedon12.github.io/tuxcast/guides/music/) ·
132
+ [Network](https://achedon12.github.io/tuxcast/guides/network/)
133
+
134
+ ## Principles
135
+
136
+ - **Reads before it writes.** `doctor` never changes anything. Other commands say what they wrote, and most take `--dry-run`.
137
+ - **Never needs root.** Everything happens in your user session. The one privileged step (the udev rule) is printed for you to run.
138
+ - **Zero dependencies.** Python's standard library only, so it installs in seconds and keeps working.
139
+ - **Explains itself.** Every warning says why it matters on stream and how to fix it.
140
+
141
+ ## Roadmap
142
+
143
+ - [x] Doctor, converter, Discord bridge, audio sinks, deck tools, patch keeper
144
+ - [ ] `tuxcast obs`: apply encoder presets and multistream outputs to an OBS profile
145
+ - [ ] More Elgato plugins in `convert` (soundboard, Spotify, Voicemeeter equivalents)
146
+ - [ ] A `doctor --watch` mode to keep in an OBS dock while live
147
+ - [ ] Packages on PyPI and the AUR
148
+
149
+ Ideas and votes go to [Discussions](https://github.com/achedon12/tuxcast/discussions).
150
+
151
+ ## Contributing
152
+
153
+ Every Linux setup is a little different, so your reports matter as much as code: a doctor
154
+ check that got your machine wrong, an Elgato action that didn't convert, a guide missing your
155
+ desktop. See [CONTRIBUTING.md](CONTRIBUTING.md). Issues labelled
156
+ [good first issue](https://github.com/achedon12/tuxcast/labels/good%20first%20issue) are a
157
+ good start; most Elgato mappings are one line.
158
+
159
+ If tuxcast saved your stream, a ⭐ helps other Linux streamers find it.
160
+
161
+ ## License
162
+
163
+ [MIT](LICENSE). tuxcast is not affiliated with Elgato, OBS, Discord, Spotify or Twitch.
@@ -0,0 +1,136 @@
1
+ <p align="center">
2
+ <img src=".github/assets/banner.svg" alt="tuxcast: the toolkit for streaming on Linux" width="100%">
3
+ </p>
4
+
5
+ <p align="center">
6
+ <a href="https://github.com/achedon12/tuxcast/actions/workflows/ci.yml"><img src="https://github.com/achedon12/tuxcast/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
7
+ <a href="https://github.com/achedon12/tuxcast/releases"><img src="https://img.shields.io/github/v/release/achedon12/tuxcast?color=8b5cf6&label=release" alt="Latest release"></a>
8
+ <img src="https://img.shields.io/badge/python-3.11%2B-3776ab" alt="Python 3.11+">
9
+ <img src="https://img.shields.io/badge/dependencies-0-22c55e" alt="Zero dependencies">
10
+ <img src="https://img.shields.io/badge/root-not%20needed-22c55e" alt="No root needed">
11
+ <a href="LICENSE"><img src="https://img.shields.io/github/license/achedon12/tuxcast?color=blue" alt="MIT license"></a>
12
+ <a href="https://achedon12.github.io/tuxcast/"><img src="https://img.shields.io/badge/docs-website-8b5cf6" alt="Documentation"></a>
13
+ </p>
14
+
15
+ <p align="center">
16
+ <b>English</b> · <a href="README.fr.md">Français</a>
17
+ </p>
18
+
19
+ **tuxcast** finds what will break your stream before you go live, then fixes it. It converts
20
+ your Elgato Stream Deck profiles, connects the apps Flatpak and snap keep apart, and splits
21
+ your audio so every source gets its own fader. One command each, no root, no dependencies.
22
+
23
+ ```sh
24
+ pipx install git+https://github.com/achedon12/tuxcast.git
25
+ tuxcast doctor
26
+ ```
27
+
28
+ <p align="center">
29
+ <a href="https://achedon12.github.io/tuxcast/#intro">
30
+ <img src=".github/assets/intro-poster.jpg" alt="Watch tuxcast in 22 seconds" width="720"><br>
31
+ <sub>▶ Watch tuxcast in 22 seconds</sub>
32
+ </a>
33
+ </p>
34
+
35
+ <p align="center">
36
+ <img src=".github/assets/terminal-doctor.svg" alt="tuxcast doctor checking a Stream Deck, Discord, Spotify and the network" width="820">
37
+ </p>
38
+
39
+ ## Why
40
+
41
+ Streaming on Linux works well, until it doesn't, and it always breaks in the same places:
42
+
43
+ - 🎛️ **Your Stream Deck.** Elgato's app does not exist for Linux, and your 8 pages of keys need rebuilding by hand.
44
+ - 🔇 **Discord keys that do nothing.** Your Stream Deck app is a Flatpak, Discord is a snap, and neither can see the other.
45
+ - ⏯️ **Media buttons that do nothing either.** The Spotify snap ignores remote control.
46
+ - 🎚️ **One audio mix.** You can't keep the music out of your VODs or lower Discord alone.
47
+ - 📶 **"Unstable bitrate."** Twitch blames your connection and your speed test says it's fine (it's the Wi-Fi).
48
+
49
+ Each of these has a fix buried in a forum thread. tuxcast checks for all of them and applies the fixes.
50
+
51
+ ## What it does
52
+
53
+ | Command | |
54
+ | --- | --- |
55
+ | [`tuxcast ui`](https://achedon12.github.io/tuxcast/commands/ui/) | Opens a control desk for everything below: a go-live tally, your Stream Deck and its pages, a mixer with faders, one-click fixes ([live demo](https://achedon12.github.io/tuxcast/demo/index.html)) |
56
+ | [`tuxcast doctor`](https://achedon12.github.io/tuxcast/commands/doctor/) | Checks display server, audio, GPU encoder, OBS, Stream Deck, Discord, Spotify and network. Each problem comes with its fix |
57
+ | [`tuxcast convert`](https://achedon12.github.io/tuxcast/commands/convert/) | Turns Elgato `.streamDeckProfile` exports into [StreamController](https://streamcontroller.core447.com/) pages: images, folders, multi actions, hotkeys (AZERTY and QWERTZ aware), OBS, Discord and Twitch keys |
58
+ | [`tuxcast bridge discord`](https://achedon12.github.io/tuxcast/commands/bridge/) | Exposes Discord's socket (snap, Vesktop, native) to Flatpak clients, and recreates the bridge at every login |
59
+ | [`tuxcast audio`](https://achedon12.github.io/tuxcast/commands/audio/) | Separate PipeWire sinks for game, music, voice and alerts, and routes apps to them |
60
+ | [`tuxcast deck`](https://achedon12.github.io/tuxcast/commands/deck/) | Lists Stream Decks, prints the udev rule they need, and resets one that froze after a crash, without unplugging it |
61
+ | [`tuxcast patch`](https://achedon12.github.io/tuxcast/commands/patch/) | Re-applies the fixes you made to app files every time an update wipes them |
62
+
63
+ ### Or run it from a control desk
64
+
65
+ `tuxcast ui` opens a dashboard on your machine: a tally that tells you whether you can go live, your
66
+ Stream Deck with its real pages, a mixer with a fader per audio channel, and a button for every fix.
67
+ [Try the live demo](https://achedon12.github.io/tuxcast/demo/index.html), no install needed.
68
+
69
+ <p align="center">
70
+ <a href="https://achedon12.github.io/tuxcast/demo/index.html">
71
+ <img src="docs/assets/ui-desk.png" alt="The tuxcast dashboard: the tally, a Stream Deck with its pages, the checks and the audio mixer" width="900">
72
+ </a>
73
+ </p>
74
+
75
+ ### Bring your Stream Deck profiles from Windows
76
+
77
+ <p align="center">
78
+ <img src=".github/assets/terminal-convert.svg" alt="tuxcast convert turning an Elgato profile into StreamController pages" width="760">
79
+ </p>
80
+
81
+ ## Install
82
+
83
+ You need Python 3.11 or newer, which every current distribution ships.
84
+
85
+ ```sh
86
+ pipx install git+https://github.com/achedon12/tuxcast.git
87
+ ```
88
+
89
+ or `uv tool install git+https://github.com/achedon12/tuxcast.git`, or the
90
+ [installer script](install.sh) (`curl -fsSL https://raw.githubusercontent.com/achedon12/tuxcast/main/install.sh | sh`).
91
+ Then start with `tuxcast doctor`.
92
+
93
+ ## Guides
94
+
95
+ The [website](https://achedon12.github.io/tuxcast/) (also in the [wiki](https://github.com/achedon12/tuxcast/wiki))
96
+ has a guide for each part of a Linux streaming setup, with the manual steps for people who
97
+ prefer to do it by hand:
98
+
99
+ [Streaming on Linux in 2026](https://achedon12.github.io/tuxcast/guides/streaming-on-linux/) ·
100
+ [OBS on Linux](https://achedon12.github.io/tuxcast/guides/obs/) ·
101
+ [Stream Deck on Linux](https://achedon12.github.io/tuxcast/guides/stream-deck/) ·
102
+ [Audio routing](https://achedon12.github.io/tuxcast/guides/audio/) ·
103
+ [Discord and Spotify in sandboxes](https://achedon12.github.io/tuxcast/guides/sandboxes/) ·
104
+ [Music without claims](https://achedon12.github.io/tuxcast/guides/music/) ·
105
+ [Network](https://achedon12.github.io/tuxcast/guides/network/)
106
+
107
+ ## Principles
108
+
109
+ - **Reads before it writes.** `doctor` never changes anything. Other commands say what they wrote, and most take `--dry-run`.
110
+ - **Never needs root.** Everything happens in your user session. The one privileged step (the udev rule) is printed for you to run.
111
+ - **Zero dependencies.** Python's standard library only, so it installs in seconds and keeps working.
112
+ - **Explains itself.** Every warning says why it matters on stream and how to fix it.
113
+
114
+ ## Roadmap
115
+
116
+ - [x] Doctor, converter, Discord bridge, audio sinks, deck tools, patch keeper
117
+ - [ ] `tuxcast obs`: apply encoder presets and multistream outputs to an OBS profile
118
+ - [ ] More Elgato plugins in `convert` (soundboard, Spotify, Voicemeeter equivalents)
119
+ - [ ] A `doctor --watch` mode to keep in an OBS dock while live
120
+ - [ ] Packages on PyPI and the AUR
121
+
122
+ Ideas and votes go to [Discussions](https://github.com/achedon12/tuxcast/discussions).
123
+
124
+ ## Contributing
125
+
126
+ Every Linux setup is a little different, so your reports matter as much as code: a doctor
127
+ check that got your machine wrong, an Elgato action that didn't convert, a guide missing your
128
+ desktop. See [CONTRIBUTING.md](CONTRIBUTING.md). Issues labelled
129
+ [good first issue](https://github.com/achedon12/tuxcast/labels/good%20first%20issue) are a
130
+ good start; most Elgato mappings are one line.
131
+
132
+ If tuxcast saved your stream, a ⭐ helps other Linux streamers find it.
133
+
134
+ ## License
135
+
136
+ [MIT](LICENSE). tuxcast is not affiliated with Elgato, OBS, Discord, Spotify or Twitch.
@@ -0,0 +1,11 @@
1
+ # contrib
2
+
3
+ Ready-made files for tuxcast and for people who prefer to set things up by hand.
4
+
5
+ | File | What it is |
6
+ | --- | --- |
7
+ | [`patches/twitch-oauth-port.toml`](patches/twitch-oauth-port.toml) | A [`tuxcast patch`](https://achedon12.github.io/tuxcast/commands/patch/) moving StreamController's Twitch login off port 3000 |
8
+ | [`udev/70-streamdeck.rules`](udev/70-streamdeck.rules) | The udev rule giving your user access to Elgato devices |
9
+
10
+ Have a patch that fixes an app for everyone? Add it here with a comment explaining why, and
11
+ open a pull request.
@@ -0,0 +1,18 @@
1
+ # StreamController's Twitch plugin listens on port 3000 for its OAuth login, which clashes with
2
+ # local web dev servers (Next.js, Vite, Rails…). This moves it to 6948.
3
+ #
4
+ # Install: cp twitch-oauth-port.toml ~/.config/tuxcast/patches/ && tuxcast patch install
5
+ # The plugin's Twitch application must allow the new redirect URI: http://localhost:6948/auth
6
+
7
+ file = "~/.var/app/com.core447.StreamController/data/plugins/com_imdevinc_StreamControllerTwitchPlugin/constants.py"
8
+
9
+ # Plugin updates delete and recreate the plugin folder, so watch its parent.
10
+ watch = "~/.var/app/com.core447.StreamController/data/plugins"
11
+
12
+ [[replace]]
13
+ pattern = '^OAUTH_PORT = \d+$'
14
+ with = "OAUTH_PORT = 6948"
15
+
16
+ [[replace]]
17
+ pattern = '^OAUTH_REDIRECT_URI = "http://localhost:\d+/auth"$'
18
+ with = 'OAUTH_REDIRECT_URI = "http://localhost:6948/auth"'
@@ -0,0 +1,6 @@
1
+ # Elgato Stream Deck: let the logged-in user talk to the device.
2
+ # Same rule as `tuxcast deck udev`. Install:
3
+ # sudo cp 70-streamdeck.rules /etc/udev/rules.d/
4
+ # sudo udevadm control --reload && sudo udevadm trigger
5
+ SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", TAG+="uaccess"
6
+ KERNEL=="hidraw*", ATTRS{idVendor}=="0fd9", TAG+="uaccess"
@@ -0,0 +1,66 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.25"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "tuxcast"
7
+ dynamic = ["version"]
8
+ description = "The toolkit for streaming on Linux: diagnose your setup, convert Elgato Stream Deck profiles, bridge sandboxed apps and split your audio."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.11"
13
+ authors = [{ name = "achedon12" }]
14
+ keywords = ["linux", "streaming", "obs", "stream-deck", "streamcontroller", "twitch", "pipewire", "discord", "flatpak"]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Environment :: Console",
18
+ "Intended Audience :: End Users/Desktop",
19
+ "Operating System :: POSIX :: Linux",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Programming Language :: Python :: 3.14",
25
+ "Topic :: Multimedia :: Video :: Capture",
26
+ "Topic :: Utilities",
27
+ ]
28
+ # No runtime dependencies on purpose: tuxcast must install anywhere with pipx in seconds.
29
+ dependencies = []
30
+
31
+ [project.urls]
32
+ Homepage = "https://achedon12.github.io/tuxcast/"
33
+ Documentation = "https://achedon12.github.io/tuxcast/"
34
+ Repository = "https://github.com/achedon12/tuxcast"
35
+ Issues = "https://github.com/achedon12/tuxcast/issues"
36
+ Changelog = "https://github.com/achedon12/tuxcast/blob/main/CHANGELOG.md"
37
+
38
+ [project.scripts]
39
+ tuxcast = "tuxcast.cli:main"
40
+
41
+ [tool.hatch.version]
42
+ path = "src/tuxcast/__init__.py"
43
+
44
+ [tool.hatch.build.targets.sdist]
45
+ include = ["src", "tests", "contrib", "README.md", "CHANGELOG.md", "LICENSE"]
46
+
47
+ [tool.pytest.ini_options]
48
+ testpaths = ["tests"]
49
+ addopts = "-ra"
50
+
51
+ [tool.ruff]
52
+ line-length = 120
53
+ target-version = "py311"
54
+ src = ["src", "tests"]
55
+
56
+ [tool.ruff.lint]
57
+ select = ["E", "F", "W", "I", "B", "UP", "SIM", "RUF", "PTH", "PL"]
58
+ ignore = [
59
+ "PLR0911", "PLR0912", "PLR0913", "PLR0915", "PLR0917", "PLR2004", "PLW0603",
60
+ "PLC0415", # lazy imports keep `tuxcast --help` fast and register doctor checks on demand
61
+ "RUF001", # the CLI prints symbols such as ✔ on purpose
62
+ ]
63
+
64
+ [tool.ruff.lint.per-file-ignores]
65
+ "tests/**" = ["PLR2004", "PLC0415"]
66
+ ".github/scripts/render-terminal.py" = ["E501"] # the SVG template reads best unwrapped
@@ -0,0 +1,3 @@
1
+ """tuxcast: the toolkit for streaming on Linux."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,3 @@
1
+ from tuxcast.cli import main
2
+
3
+ raise SystemExit(main())