Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
c16ff33
Fix test_initial_state() test failure on apple silicon.
jcheek Jul 26, 2025
d29dcf7
fix: update PyTorch CUDA version from cu129 to cu126
ryan-steed-usa Oct 30, 2025
88f04b1
add gpt-4o-mini-tts
AlistairKeiller Dec 26, 2025
af74c5f
add to json
AlistairKeiller Dec 26, 2025
3970312
fix: OGG/Opus truncation — close container before reading buffer
Feb 14, 2026
5e55b5c
fix(web): add Firefox-safe audio playback fallback when MSE MP3 is un…
JiminyScript Apr 23, 2026
b32d6b4
fix: cache voice tensors to prevent per-request memory leak
May 8, 2026
878fd5d
fix: use weights_only=True for voice tensor torch.load calls
dashitongzhi May 8, 2026
ec99172
Merge pull request #370 from ziquid/feature/ziquid-fix-test-initial-s…
remsky May 9, 2026
be325d4
Merge pull request #433 from AlistairKeiller/master
remsky May 9, 2026
a19bf83
Merge pull request #448 from will-assistant/fix/opus-truncation
remsky May 9, 2026
4f01096
Merge pull request #460 from dashitongzhi/fix/torch-load-weights-only
remsky May 9, 2026
430ea74
Merge pull request #459 from KeloYuan/fix/voice-tensor-memory-leak
remsky May 9, 2026
a82860b
fix: clear voice cache on unload, correct temp file age check, align …
remsky May 10, 2026
1e09bfb
examples: add transcription accuracy test harness with baselines
remsky May 10, 2026
75a98b6
Merge pull request #407 from ryan-steed-usa/pytorch-cu126
remsky May 11, 2026
0c50b03
build(docker): add multi-stage for ~45% gpu image trim, align gpu bas…
remsky May 11, 2026
c84adf3
fix(tests): drop tautological load_model_validation
remsky May 11, 2026
ff8252a
ci(release): pin buildkit/runners, fix workflow_dispatch ref + tag-ch…
remsky May 14, 2026
0d35239
Merge PR #458 from JiminyScript: Firefox MSE fallback
remsky May 14, 2026
a10fc75
fix(web): firefox/supported playback handling and msging, bmac link, …
remsky May 15, 2026
4ecbfe4
docs(readme): whisper validatons, version notes, feature bumps
remsky May 15, 2026
b51d455
Revise README with updated features and languages
remsky May 19, 2026
7bbd3a8
fix(mappings): /v1/audio/voices returns id/name objects (#462) to ali…
remsky May 21, 2026
0cf239e
fix(docker): compose defaults to idempotent model download; harden do…
remsky May 21, 2026
255e559
test: add integration suite + tts-api-test-client image; drop superse…
remsky May 22, 2026
8e1bafe
feat(web): show server version badge in the UI footer
remsky May 22, 2026
4fca67d
chore: CHANGELOG, version candidate, examples requests bump
remsky May 22, 2026
54b317e
chore: merge origin readme changes
remsky May 22, 2026
3803f86
docs: fix badge links in README.md
remsky May 22, 2026
94f729f
fix(tests): lazy import integration reqs, exclude on CI
remsky May 22, 2026
3b01836
Merge branch 'master' of https://github.com/remsky/Kokoro-FastAPI
remsky May 22, 2026
c6398b9
fix(ci): run the test job with the cpu extra
remsky May 22, 2026
64cb068
fix: int16 overflow in silence-trim, invalid-escape in URL regex
remsky May 22, 2026
ee2b44c
chore(changelog): update unreleased changes
remsky May 22, 2026
65ef3b8
feat(gpu): adds clear cu128 opt-in via compose, setup for Blackwell /…
remsky May 23, 2026
0d6b4d8
fix(docker): aligns cu128 base image with wheel (12.9.1 → 12.8.1), m…
remsky May 23, 2026
f08279f
feat(gpu): adds clear cu128 opt-in via compose, setup for Blackwell
remsky May 23, 2026
f9bde23
chore(bake): explicit wheel variant in per-arch gpu tags (cu126/cu128…
remsky May 23, 2026
7649d86
fix(audio): drop WAV close()-time junk trailer that caused chunk-end …
remsky May 24, 2026
75acf86
chore(docker): add oci metadata, copy VERSION for web ui, prebuilt im…
remsky May 24, 2026
8ce0821
fix(rocm): persist MIOpen cache and add FIND_MODE=2 default +warmup s…
remsky May 25, 2026
291d4d5
chore(release): bump and minor docs, release notes
remsky May 25, 2026
3f64dc2
fix(webui): bounded buffer to resolve 10 minute crashout, player stat…
remsky May 27, 2026
ff6efaf
feat(api): add POST /dev/unload to release model from GPU VRAM (#474)
sageframe-no-kaji Jun 3, 2026
6b58b53
feat(benchmarks): add model unload benchmarking script and update REA…
remsky Jun 4, 2026
2153529
fix(audio): implement audio file source swapping for stream playback …
remsky Jun 6, 2026
b7e39bc
chore: actions bumps + ruff formatting
remsky Jun 6, 2026
4129920
chore(release): bump to v0.5.0, new endpoint, UI features
remsky Jun 6, 2026
c5ccfa1
fix(mappings): update voice mappings for consistency, add missing aud…
remsky Jun 18, 2026
24ac58e
fix(dev-unload): Prevent POST /dev/unload behind an opt-in setting (#…
sanjaygulati13 Jul 12, 2026
c0acb91
fix: word timestamps for non-English (espeak) voices in captioned_spe…
mlevinmail Jul 12, 2026
316aa67
fix(debug-endpoints): gate /debug/* introspection routes behind ENABL…
remsky Jul 12, 2026
8329a07
chore(release): bump to v0.6.0, opt-in dev/debug endpoints, voice + t…
remsky Jul 12, 2026
b291abe
chore(ci): bump docker/login-action to v4, re: node 20 deprecation wa…
remsky Jul 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .codeql-config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
paths:
- api
- ui
paths-ignore:
- .venv
- "**/node_modules"
- "**/__pycache__"
- examples
- docs
- "**/tests/**"
9 changes: 3 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ on:
branches: [ "master", "pre-release" ]
jobs:
test:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
strategy:
matrix:
python-version: ["3.10"]
fail-fast: false

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

# Match Dockerfile dependencies
- name: Install Dependencies
Expand All @@ -34,9 +34,6 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
enable-cache: true
- name: Install dependencies
run: |
uv pip install -e .[test,cpu]
- name: Run Tests
run: |
uv run pytest api/tests/ --asyncio-mode=auto --cov=api --cov-report=term-missing
uv run --extra test --extra cpu pytest api/tests/ --asyncio-mode=auto --cov=api --cov-report=term-missing
187 changes: 145 additions & 42 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,38 @@ on:
required: true
type: string

concurrency:
group: release-${{ github.event_name == 'workflow_dispatch' && inputs.branch_name || github.ref_name }}
cancel-in-progress: false

jobs:
prepare-release:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
outputs:
version: ${{ steps.get-version.outputs.version }}
version_tag: ${{ steps.get-version.outputs.version_tag }}
source_ref: ${{ steps.resolve-ref.outputs.source_ref }}
steps:
- name: Resolve source ref
id: resolve-ref
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
echo "source_ref=${{ inputs.branch_name }}" >> $GITHUB_OUTPUT
else
echo "source_ref=${{ github.ref_name }}" >> $GITHUB_OUTPUT
fi

- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
ref: ${{ steps.resolve-ref.outputs.source_ref }}
fetch-depth: 0

- name: Get version from VERSION file
id: get-version
run: |
VERSION_PLAIN=$(cat VERSION)

if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
BRANCH_NAME="${{ inputs.branch_name }}"
else
BRANCH_NAME="${{ github.ref_name }}"
fi
BRANCH_NAME="${{ steps.resolve-ref.outputs.source_ref }}"

if [[ "$BRANCH_NAME" == "release" ]]; then
echo "version=${VERSION_PLAIN}" >> $GITHUB_OUTPUT
Expand All @@ -44,6 +56,15 @@ jobs:
echo "version_tag=v${VERSION_PLAIN}-${SAFE_BRANCH}" >> $GITHUB_OUTPUT
fi

- name: Check tag does not exist
run: |
TAG_NAME="${{ steps.get-version.outputs.version_tag }}"
git fetch --tags
if git rev-parse "$TAG_NAME" >/dev/null 2>&1; then
echo "::error::Tag $TAG_NAME already exists. Please increment the version in the VERSION file."
exit 1
fi

build-images:
needs: prepare-release
permissions:
Expand All @@ -60,10 +81,13 @@ jobs:
include:
- build_target: "cpu"
platform: "linux/amd64"
runs_on: "ubuntu-latest"
runs_on: "ubuntu-24.04"
- build_target: "gpu"
platform: "linux/amd64"
runs_on: "ubuntu-latest"
runs_on: "ubuntu-24.04"
- build_target: "gpu-cu128"
platform: "linux/amd64"
runs_on: "ubuntu-24.04"
- build_target: "cpu"
platform: "linux/arm64"
runs_on: "ubuntu-24.04-arm"
Expand All @@ -72,25 +96,13 @@ jobs:
runs_on: "ubuntu-24.04-arm"
- build_target: "rocm"
platform: "linux/amd64"
runs_on: "ubuntu-latest"
runs_on: "ubuntu-24.04"
runs-on: ${{ matrix.runs_on }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0 # Needed to check for existing tags

- name: Check if tag already exists
run: |
TAG_NAME="${{ needs.prepare-release.outputs.version_tag }}"
echo "Checking for existing tag: $TAG_NAME"
git fetch --tags
if git rev-parse "$TAG_NAME" >/dev/null 2>&1; then
echo "::error::Tag $TAG_NAME already exists. Please increment the version in the VERSION file."
exit 1
else
echo "Tag $TAG_NAME does not exist. Proceeding with release."
fi
ref: ${{ needs.prepare-release.outputs.source_ref }}

- name: Free disk space
run: |
Expand All @@ -103,14 +115,14 @@ jobs:
df -h

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 # Use v3
uses: docker/setup-buildx-action@v4
with:
driver-opts: |
image=moby/buildkit:latest
image=moby/buildkit:v0.21.1
network=host

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3 # Use v3
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand All @@ -127,11 +139,18 @@ jobs:
TARGET="${BUILD_TARGET}-$(echo ${PLATFORM} | cut -d'/' -f2)"
echo "Using bake target: $TARGET"

docker buildx bake $TARGET --push --progress=plain
# Bake reads REVISION/CREATED as HCL variables; both populate
# org.opencontainers.image.* labels and annotations on the per-arch push.
export REVISION="${GITHUB_SHA}"
export CREATED="$(date -u +%Y-%m-%dT%H:%M:%SZ)"

docker buildx bake $TARGET --push --progress=plain \
--set "*.cache-from=type=gha,scope=${TARGET}" \
--set "*.cache-to=type=gha,mode=max,scope=${TARGET}"

create-manifests:
needs: [prepare-release, build-images]
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
permissions:
packages: write
env:
Expand All @@ -140,10 +159,10 @@ jobs:
REPO: ${{ vars.REPO || 'kokoro-fastapi' }}
strategy:
matrix:
build_target: ["cpu", "gpu", "rocm"]
build_target: ["cpu", "gpu", "gpu-cu128", "rocm"]
steps:
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand All @@ -157,34 +176,118 @@ jobs:
OWNER="${{ env.OWNER }}"
REPO="${{ env.REPO }}"

docker buildx imagetools create -t \
${REGISTRY}/${OWNER}/${REPO}-${TARGET}:${VERSION_TAG} \
${REGISTRY}/${OWNER}/${REPO}-${TARGET}:${VERSION_TAG}-amd64 \
${REGISTRY}/${OWNER}/${REPO}-${TARGET}:${VERSION_TAG}-arm64
# Resolve the package name, manifest tag(s), and source images per target.
#
# Tag layout per target:
# - cpu: :VERSION + :latest (multi-arch)
# - gpu: :VERSION + :VERSION-cu126 + :latest + :latest-cu126
# (the -cu126 aliases make the wheel variant explicit so
# Maxwell/Pascal users can pin it across future default flips)
# - gpu-cu128: :VERSION-cu128 + :latest-cu128 (amd64 only)
# - rocm: :VERSION + :latest (amd64 only)
#
# MANIFEST_TAGS / LATEST_TAGS are space-separated lists; all entries point at
# the same SOURCES so the underlying blobs are deduplicated by digest.
#
# TITLE / DESCRIPTION are attached as index-level OCI annotations.
# GHCR reads org.opencontainers.image.description from the index manifest
# for multi-arch packages, so the per-arch labels set by bake are not
# enough on their own.
case "$TARGET" in
gpu-cu128)
PACKAGE="${REPO}-gpu"
MANIFEST_TAGS="${VERSION_TAG}-cu128"
LATEST_TAGS="latest-cu128"
SOURCES=("${REGISTRY}/${OWNER}/${PACKAGE}:${VERSION_TAG}-cu128-amd64")
TITLE="Kokoro-FastAPI (GPU, cu128 / Blackwell)"
DESCRIPTION="Kokoro TTS served via FastAPI. NVIDIA GPU build with CUDA 12.8 + cu128 torch wheels for RTX 50-series (Blackwell, sm_120). amd64 only."
;;
gpu)
PACKAGE="${REPO}-gpu"
MANIFEST_TAGS="${VERSION_TAG} ${VERSION_TAG}-cu126"
LATEST_TAGS="latest latest-cu126"
# Per-arch sources carry their wheel variant (cu126 amd64, cu129 arm64);
# both feed the same multi-arch manifest tags above.
SOURCES=(
"${REGISTRY}/${OWNER}/${PACKAGE}:${VERSION_TAG}-cu126-amd64"
"${REGISTRY}/${OWNER}/${PACKAGE}:${VERSION_TAG}-cu129-arm64"
)
TITLE="Kokoro-FastAPI (GPU)"
DESCRIPTION="Kokoro TTS served via FastAPI. NVIDIA GPU build, multi-arch (CUDA 12.6 + cu126 wheels on amd64, CUDA 12.9 + cu129 wheels on arm64). See the -cu128 tag for Blackwell."
;;
rocm)
PACKAGE="${REPO}-rocm"
MANIFEST_TAGS="${VERSION_TAG}"
LATEST_TAGS="latest"
SOURCES=("${REGISTRY}/${OWNER}/${PACKAGE}:${VERSION_TAG}-amd64")
TITLE="Kokoro-FastAPI (ROCm)"
DESCRIPTION="Kokoro TTS served via FastAPI. AMD ROCm build. amd64 only."
;;
*)
PACKAGE="${REPO}-${TARGET}"
MANIFEST_TAGS="${VERSION_TAG}"
LATEST_TAGS="latest"
SOURCES=(
"${REGISTRY}/${OWNER}/${PACKAGE}:${VERSION_TAG}-amd64"
"${REGISTRY}/${OWNER}/${PACKAGE}:${VERSION_TAG}-arm64"
)
TITLE="Kokoro-FastAPI (CPU)"
DESCRIPTION="Kokoro TTS served via FastAPI. CPU build, multi-arch (amd64 + arm64)."
;;
esac

# Common index annotations. `index:` is required so these land on the
# index manifest itself, not on per-platform descriptors inside it.
SOURCE_URL="https://github.com/${OWNER}/Kokoro-FastAPI"
CREATED="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
REVISION="${GITHUB_SHA}"
ANNOTATIONS=(
--annotation "index:org.opencontainers.image.title=${TITLE}"
--annotation "index:org.opencontainers.image.description=${DESCRIPTION}"
--annotation "index:org.opencontainers.image.source=${SOURCE_URL}"
--annotation "index:org.opencontainers.image.url=${SOURCE_URL}"
--annotation "index:org.opencontainers.image.licenses=Apache-2.0"
--annotation "index:org.opencontainers.image.version=${VERSION_TAG}"
--annotation "index:org.opencontainers.image.revision=${REVISION}"
--annotation "index:org.opencontainers.image.created=${CREATED}"
)

for TAG in $MANIFEST_TAGS; do
docker buildx imagetools create \
"${ANNOTATIONS[@]}" \
-t ${REGISTRY}/${OWNER}/${PACKAGE}:${TAG} \
"${SOURCES[@]}"
done

# Publish the rolling tag(s) only for clean release tags (no branch suffix).
if [[ "$VERSION_TAG" != *"-"* ]]; then
docker buildx imagetools create -t \
${REGISTRY}/${OWNER}/${REPO}-${TARGET}:latest \
${REGISTRY}/${OWNER}/${REPO}-${TARGET}:${VERSION_TAG}-amd64 \
${REGISTRY}/${OWNER}/${REPO}-${TARGET}:${VERSION_TAG}-arm64
for TAG in $LATEST_TAGS; do
docker buildx imagetools create \
"${ANNOTATIONS[@]}" \
-t ${REGISTRY}/${OWNER}/${PACKAGE}:${TAG} \
"${SOURCES[@]}"
done
fi

create-release:
needs: [prepare-release, create-manifests]
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.prepare-release.outputs.version_tag }}
target_commitish: ${{ needs.prepare-release.outputs.source_ref }}
name: Release ${{ needs.prepare-release.outputs.version_tag }}
body: |
Curated summary: [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.prepare-release.outputs.version_tag }}/CHANGELOG.md)
generate_release_notes: true
draft: false
prerelease: false
Expand Down
22 changes: 14 additions & 8 deletions .github/workflows/test_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ on:
- all
- cpu
- gpu
- gpu-cu128
- rocm
platform:
description: 'Platform (ignored for rocm)'
Expand All @@ -36,19 +37,20 @@ concurrency:

jobs:
setup:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Build matrix
id: set-matrix
run: |
ALL_TARGETS='[
{"build_target":"cpu","platform":"amd64","runs_on":"ubuntu-latest"},
{"build_target":"cpu","platform":"amd64","runs_on":"ubuntu-24.04"},
{"build_target":"cpu","platform":"arm64","runs_on":"ubuntu-24.04-arm"},
{"build_target":"gpu","platform":"amd64","runs_on":"ubuntu-latest"},
{"build_target":"gpu","platform":"amd64","runs_on":"ubuntu-24.04"},
{"build_target":"gpu","platform":"arm64","runs_on":"ubuntu-24.04-arm"},
{"build_target":"rocm","platform":"amd64","runs_on":"ubuntu-latest"}
{"build_target":"gpu-cu128","platform":"amd64","runs_on":"ubuntu-24.04"},
{"build_target":"rocm","platform":"amd64","runs_on":"ubuntu-24.04"}
]'

FILTERED=$(echo "$ALL_TARGETS" | jq -c \
Expand Down Expand Up @@ -77,7 +79,7 @@ jobs:
runs-on: ${{ matrix.runs_on }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
ref: ${{ inputs.branch_name }}

Expand All @@ -86,15 +88,19 @@ jobs:
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
with:
driver-opts: image=moby/buildkit:v0.21.1

- name: Build image
run: |
TARGET="${{ matrix.build_target }}-${{ matrix.platform }}"
CACHE_ARGS=(
--set "*.cache-from=type=gha,scope=${TARGET}"
--set "*.cache-to=type=gha,mode=max,scope=${TARGET}"
)
if [[ "${{ inputs.dry_run }}" == "true" ]]; then
docker buildx bake "$TARGET" --print
docker buildx bake "$TARGET" --print "${CACHE_ARGS[@]}"
else
docker buildx bake "$TARGET" --progress=plain
docker buildx bake "$TARGET" --progress=plain "${CACHE_ARGS[@]}"
fi
Loading