-
Notifications
You must be signed in to change notification settings - Fork 0
fix(docker): ship demo-image plugins as directory bundles #567
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,6 +31,8 @@ import ( | |
| const ( | ||
| defaultSkitURL = "http://127.0.0.1:4545" | ||
| defaultListenAddr = ":8080" | ||
| // Matches the Whisper model bundled in the -demo images. | ||
| defaultSTTModel = "models/ggml-tiny-q5_1.bin" | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📝 Info: Default STT model changed from base.en to tiny — intentional fix, not a regression The old hardcoded model path was Was this helpful? React with 👍 or 👎 to provide feedback. Debug |
||
|
|
||
| sttPipelineYAML = ` | ||
| name: stt-ogg-opus | ||
|
|
@@ -53,7 +55,7 @@ steps: | |
|
|
||
| - kind: plugin::native::whisper | ||
| params: | ||
| model_path: models/ggml-base.en-q5_1.bin | ||
| model_path: %s | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📝 Info: Unquoted fmt.Sprintf substitution into YAML template is safe for file paths but fragile for arbitrary strings The Was this helpful? React with 👍 or 👎 to provide feedback. Debug |
||
| language: en | ||
| vad_model_path: models/silero_vad.onnx | ||
| vad_threshold: 0.5 | ||
|
|
@@ -110,6 +112,7 @@ type gateway struct { | |
| authToken string | ||
| maxBodySize int64 | ||
| maxTTSTextSize int64 | ||
| sttPipeline string | ||
| sem chan struct{} | ||
| } | ||
|
|
||
|
|
@@ -120,6 +123,7 @@ type config struct { | |
| maxConcurrency int | ||
| maxBodySize int64 | ||
| maxTTSTextSize int64 | ||
| sttModel string | ||
| } | ||
|
|
||
| func main() { | ||
|
|
@@ -130,6 +134,7 @@ func main() { | |
| authToken: cfg.authToken, | ||
| maxBodySize: cfg.maxBodySize, | ||
| maxTTSTextSize: cfg.maxTTSTextSize, | ||
| sttPipeline: fmt.Sprintf(sttPipelineYAML, cfg.sttModel), | ||
| sem: make(chan struct{}, cfg.maxConcurrency), | ||
| } | ||
|
|
||
|
|
@@ -159,6 +164,7 @@ func loadConfig() config { | |
| maxConc := flagInt("max-concurrency", envInt("GATEWAY_MAX_CONCURRENCY", 10), "Maximum concurrent in-flight requests") | ||
| maxBody := flagInt64("max-body-bytes", envInt64("GATEWAY_MAX_BODY_BYTES", 1*1024*1024), "Maximum request body size") | ||
| maxTTSText := flagInt64("max-tts-text-size", envInt64("GATEWAY_MAX_TTS_TEXT_SIZE", 1000), "Maximum TTS text size in characters") | ||
| sttModel := flagString("stt-model", getEnvDefault("GATEWAY_STT_MODEL", defaultSTTModel), "Whisper model path used by the STT pipeline (relative to the skit working dir)") | ||
|
|
||
| flag.Parse() | ||
|
|
||
|
|
@@ -169,6 +175,7 @@ func loadConfig() config { | |
| maxConcurrency: *maxConc, | ||
| maxBodySize: *maxBody, | ||
| maxTTSTextSize: *maxTTSText, | ||
| sttModel: *sttModel, | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -262,7 +269,7 @@ func (gw *gateway) handleSTT(w http.ResponseWriter, r *http.Request) { | |
| defer release() | ||
| r.Body = http.MaxBytesReader(underlying(w), r.Body, gw.maxBodySize) | ||
| useBuffer := r.ContentLength > 0 && r.ContentLength <= gw.maxBodySize | ||
| gw.proxyMultipart(w, r, "stt", sttPipelineYAML, "media", "audio/ogg", useBuffer) | ||
| gw.proxyMultipart(w, r, "stt", gw.sttPipeline, "media", "audio/ogg", useBuffer) | ||
| } | ||
|
|
||
| func (gw *gateway) handleTTS(w http.ResponseWriter, r *http.Request) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,24 +3,34 @@ | |
| # | ||
| # SPDX-License-Identifier: MPL-2.0 | ||
|
|
||
| # The -demo images currently ship native plugins as bare `.so` files under | ||
| # Older -demo images (<= v0.5.0) ship native plugins as bare `.so` files under | ||
| # plugins/native/, but the loader expects directory bundles | ||
| # (plugins/native/<id>/ with a plugin.yml + the .so). Without this, `skit serve` | ||
| # logs "no plugins found" and TTS/STT pipelines fail with "node kind not found". | ||
| # We assemble the expected layout from the repo manifests (mounted at | ||
| # /repo-manifests) plus the .so files baked into the image, then start the | ||
| # server. The proper fix is in Dockerfile.demo (ship the bundles directly); | ||
| # tracked in https://github.com/streamer45/streamkit/issues/553 — remove this | ||
| # shim once the demo image ships plugin bundles. | ||
| # We pass through any directory bundles the image already ships (newer images, | ||
| # see https://github.com/streamer45/streamkit/issues/553) and assemble the rest | ||
| # from the repo manifests (mounted at /repo-manifests) plus the bare .so files | ||
| # baked into the image, then start the server. Remove this shim once the pinned | ||
| # image ships plugin bundles. | ||
| set -e | ||
|
|
||
| SRC=/opt/streamkit/plugins/native | ||
| DST=/opt/streamkit/np/native | ||
| mkdir -p "$DST" | ||
|
Comment on lines
18
to
19
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚩 Entrypoint.sh permission assumption for /opt/streamkit/np The entrypoint.sh ( Was this helpful? React with 👍 or 👎 to provide feedback. Debug |
||
|
|
||
| for dir in "$SRC"/*/; do | ||
| [ -d "$dir" ] || continue | ||
| id=$(basename "$dir") | ||
| if [ -f "$dir/plugin.yml" ] && ls "$dir"/*.so > /dev/null 2>&1; then | ||
| cp -r "$SRC/$id" "$DST/$id" | ||
| echo "copied plugin bundle: $id" | ||
| fi | ||
| done | ||
|
|
||
| for manifest in /repo-manifests/*/plugin.yml; do | ||
| [ -f "$manifest" ] || continue | ||
| id=$(basename "$(dirname "$manifest")") | ||
| [ -d "$DST/$id" ] && continue | ||
|
Comment on lines
+21
to
+33
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📝 Info: entrypoint.sh correctly handles both old and new plugin layouts without conflict The updated Was this helpful? React with 👍 or 👎 to provide feedback. Debug |
||
| so=$(awk '/^entrypoint:/{print $2}' "$manifest" | tr -d '\r') | ||
| if [ -n "$so" ] && [ -f "$SRC/$so" ]; then | ||
| mkdir -p "$DST/$id" | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📝 Info: First COPY uses /build/dist (full tree) while subsequent COPYs use specific subdirectories
The whisper plugin is copied with
COPY --from=whisper-builder /build/dist /opt/streamkit/plugins(line 647), which bootstraps the entireplugins/native/tree structure. All subsequent plugins use targeted paths likeCOPY --from=kokoro-builder /build/dist/native/kokoro /opt/streamkit/plugins/native/kokoro(line 651). This asymmetry is intentional: the first COPY creates thenative/directory hierarchy, and subsequent COPYs merge individual plugin directories into it. If whisper were ever removed, the first plugin in the list would need to use the full-tree COPY pattern instead to create the directory structure.Was this helpful? React with 👍 or 👎 to provide feedback.
Debug
Playground