mirror of
https://github.com/remsky/Kokoro-FastAPI.git
synced 2025-08-05 16:48:53 +00:00
Bump version to 0.3.0 and update related configurations; add misaki patch script and remove obsolete build workflow
This commit is contained in:
parent
e2313abe72
commit
6a2d3a54cf
15 changed files with 411 additions and 297 deletions
87
.github/workflows/build-push.yml
vendored
87
.github/workflows/build-push.yml
vendored
|
@ -1,87 +0,0 @@
|
||||||
name: Docker Build and push
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags: [ 'v*.*.*' ]
|
|
||||||
paths-ignore:
|
|
||||||
- '**.md'
|
|
||||||
- 'docs/**'
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
version:
|
|
||||||
description: 'Version to build and publish (e.g. v0.2.0)'
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
prepare-release:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
version: ${{ steps.get-version.outputs.version }}
|
|
||||||
is_prerelease: ${{ steps.check-prerelease.outputs.is_prerelease }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Get version
|
|
||||||
id: get-version
|
|
||||||
run: |
|
|
||||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
||||||
echo "version=${{ inputs.version }}" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Check if prerelease
|
|
||||||
id: check-prerelease
|
|
||||||
run: |
|
|
||||||
echo "is_prerelease=${{ contains(steps.get-version.outputs.version, '-pre') }}" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
build-images:
|
|
||||||
needs: prepare-release
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
packages: write
|
|
||||||
env:
|
|
||||||
DOCKER_BUILDKIT: 1
|
|
||||||
BUILDKIT_STEP_LOG_MAX_SIZE: 10485760
|
|
||||||
# This environment variable will override the VERSION variable in your HCL file.
|
|
||||||
VERSION: ${{ needs.prepare-release.outputs.version }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Free disk space
|
|
||||||
run: |
|
|
||||||
echo "Listing current disk space"
|
|
||||||
df -h
|
|
||||||
echo "Cleaning up disk space..."
|
|
||||||
sudo rm -rf /usr/share/dotnet
|
|
||||||
sudo rm -rf /usr/local/lib/android
|
|
||||||
sudo rm -rf /opt/ghc
|
|
||||||
sudo rm -rf /opt/hostedtoolcache
|
|
||||||
docker system prune -af
|
|
||||||
echo "Disk space after cleanup"
|
|
||||||
df -h
|
|
||||||
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v2
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v2
|
|
||||||
with:
|
|
||||||
driver-opts: |
|
|
||||||
image=moby/buildkit:latest
|
|
||||||
network=host
|
|
||||||
|
|
||||||
- name: Log in to GitHub Container Registry
|
|
||||||
uses: docker/login-action@v2
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build and push images
|
|
||||||
run: |
|
|
||||||
# No need to override VERSION via --set; the env var does the job.
|
|
||||||
docker buildx bake --push
|
|
102
.github/workflows/docker-publish.yml
vendored
102
.github/workflows/docker-publish.yml
vendored
|
@ -1,102 +0,0 @@
|
||||||
name: Docker Build and Publish
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags: [ 'v*.*.*' ]
|
|
||||||
paths-ignore:
|
|
||||||
- '**.md'
|
|
||||||
- 'docs/**'
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
version:
|
|
||||||
description: 'Version to release (e.g. v0.2.0)'
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
prepare-release:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
version: ${{ steps.get-version.outputs.version }}
|
|
||||||
is_prerelease: ${{ steps.check-prerelease.outputs.is_prerelease }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Get version
|
|
||||||
id: get-version
|
|
||||||
run: |
|
|
||||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
||||||
echo "version=${{ inputs.version }}" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Check if prerelease
|
|
||||||
id: check-prerelease
|
|
||||||
run: echo "is_prerelease=${{ contains(steps.get-version.outputs.version, '-pre') }}" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
build-images:
|
|
||||||
needs: prepare-release
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
packages: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Free disk space
|
|
||||||
run: |
|
|
||||||
echo "Listing current disk space"
|
|
||||||
df -h
|
|
||||||
echo "Cleaning up disk space..."
|
|
||||||
sudo rm -rf /usr/share/dotnet
|
|
||||||
sudo rm -rf /usr/local/lib/android
|
|
||||||
sudo rm -rf /opt/ghc
|
|
||||||
sudo rm -rf /opt/hostedtoolcache
|
|
||||||
docker system prune -af
|
|
||||||
echo "Disk space after cleanup"
|
|
||||||
df -h
|
|
||||||
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v2
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v2
|
|
||||||
with:
|
|
||||||
driver-opts: |
|
|
||||||
image=moby/buildkit:latest
|
|
||||||
network=host
|
|
||||||
|
|
||||||
- name: Log in to GitHub Container Registry
|
|
||||||
uses: docker/login-action@v2
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build and push images
|
|
||||||
env:
|
|
||||||
DOCKER_BUILDKIT: 1
|
|
||||||
BUILDKIT_STEP_LOG_MAX_SIZE: 10485760
|
|
||||||
VERSION: ${{ needs.prepare-release.outputs.version }}
|
|
||||||
run: docker buildx bake --push
|
|
||||||
|
|
||||||
create-release:
|
|
||||||
needs: [prepare-release, build-images]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Create Release
|
|
||||||
uses: softprops/action-gh-release@v1
|
|
||||||
with:
|
|
||||||
tag_name: ${{ needs.prepare-release.outputs.version }}
|
|
||||||
generate_release_notes: true
|
|
||||||
draft: true
|
|
||||||
prerelease: ${{ needs.prepare-release.outputs.is_prerelease }}
|
|
95
.github/workflows/release.yml
vendored
Normal file
95
.github/workflows/release.yml
vendored
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
name: Create Release and Publish Docker Images
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- release # Trigger when commits are pushed to the release branch (e.g., after merging master)
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
- 'docs/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
prepare-release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
version: ${{ steps.get-version.outputs.version }}
|
||||||
|
version_tag: ${{ steps.get-version.outputs.version_tag }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Get version from VERSION file
|
||||||
|
id: get-version
|
||||||
|
run: |
|
||||||
|
VERSION_PLAIN=$(cat VERSION)
|
||||||
|
echo "version=${VERSION_PLAIN}" >> $GITHUB_OUTPUT
|
||||||
|
echo "version_tag=v${VERSION_PLAIN}" >> $GITHUB_OUTPUT # Add 'v' prefix for tag
|
||||||
|
|
||||||
|
build-images:
|
||||||
|
needs: prepare-release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
packages: write # Needed to push images to GHCR
|
||||||
|
env:
|
||||||
|
DOCKER_BUILDKIT: 1
|
||||||
|
BUILDKIT_STEP_LOG_MAX_SIZE: 10485760
|
||||||
|
# This environment variable will override the VERSION variable in docker-bake.hcl
|
||||||
|
VERSION: ${{ needs.prepare-release.outputs.version_tag }} # Use tag version (vX.Y.Z) for bake
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Free disk space # Optional: Keep if needed for large builds
|
||||||
|
run: |
|
||||||
|
echo "Listing current disk space"
|
||||||
|
df -h
|
||||||
|
echo "Cleaning up disk space..."
|
||||||
|
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache
|
||||||
|
docker system prune -af
|
||||||
|
echo "Disk space after cleanup"
|
||||||
|
df -h
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3 # Use v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3 # Use v3
|
||||||
|
with:
|
||||||
|
driver-opts: |
|
||||||
|
image=moby/buildkit:latest
|
||||||
|
network=host
|
||||||
|
|
||||||
|
- name: Log in to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3 # Use v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and push images using Docker Bake
|
||||||
|
run: |
|
||||||
|
echo "Building and pushing images for version ${{ needs.prepare-release.outputs.version_tag }}"
|
||||||
|
# The VERSION env var above sets the tag for the bake file targets
|
||||||
|
docker buildx bake --push
|
||||||
|
|
||||||
|
create-release:
|
||||||
|
needs: [prepare-release, build-images]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write # Needed to create releases
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Fetch all history for release notes generation
|
||||||
|
|
||||||
|
- name: Create GitHub Release
|
||||||
|
uses: softprops/action-gh-release@v2 # Use v2
|
||||||
|
with:
|
||||||
|
tag_name: ${{ needs.prepare-release.outputs.version_tag }} # Use vX.Y.Z tag
|
||||||
|
name: Release ${{ needs.prepare-release.outputs.version_tag }}
|
||||||
|
generate_release_notes: true # Auto-generate release notes
|
||||||
|
draft: false # Publish immediately
|
||||||
|
prerelease: false # Mark as a stable release
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
20
README.md
20
README.md
|
@ -3,12 +3,12 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
# <sub><sub>_`FastKoko`_ </sub></sub>
|
# <sub><sub>_`FastKoko`_ </sub></sub>
|
||||||
[]()
|
[]()
|
||||||
[]()
|
[]()
|
||||||
[](https://huggingface.co/spaces/Remsky/Kokoro-TTS-Zero)
|
[](https://huggingface.co/spaces/Remsky/Kokoro-TTS-Zero)
|
||||||
|
|
||||||
[](https://github.com/hexgrad/kokoro)
|
[](https://github.com/hexgrad/kokoro)
|
||||||
[](https://github.com/hexgrad/misaki)
|
[](https://github.com/hexgrad/misaki)
|
||||||
|
|
||||||
[](https://huggingface.co/hexgrad/Kokoro-82M/commit/9901c2b79161b6e898b7ea857ae5298f47b8b0d6)
|
[](https://huggingface.co/hexgrad/Kokoro-82M/commit/9901c2b79161b6e898b7ea857ae5298f47b8b0d6)
|
||||||
|
|
||||||
|
@ -24,10 +24,6 @@ Dockerized FastAPI wrapper for [Kokoro-82M](https://huggingface.co/hexgrad/Kokor
|
||||||
### Integration Guides
|
### Integration Guides
|
||||||
[](https://github.com/remsky/Kokoro-FastAPI/wiki/Setup-Kubernetes) [](https://github.com/remsky/Kokoro-FastAPI/wiki/Integrations-DigitalOcean) [](https://github.com/remsky/Kokoro-FastAPI/wiki/Integrations-SillyTavern)
|
[](https://github.com/remsky/Kokoro-FastAPI/wiki/Setup-Kubernetes) [](https://github.com/remsky/Kokoro-FastAPI/wiki/Integrations-DigitalOcean) [](https://github.com/remsky/Kokoro-FastAPI/wiki/Integrations-SillyTavern)
|
||||||
[](https://github.com/remsky/Kokoro-FastAPI/wiki/Integrations-OpenWebUi)
|
[](https://github.com/remsky/Kokoro-FastAPI/wiki/Integrations-OpenWebUi)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Get Started
|
## Get Started
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
@ -41,8 +37,8 @@ Refer to the core/config.py file for a full list of variables which can be manag
|
||||||
# the `latest` tag can be used, but should not be considered stable as it may include `nightly` branch builds
|
# the `latest` tag can be used, but should not be considered stable as it may include `nightly` branch builds
|
||||||
# it may have some bonus features however, and feedback/testing is welcome
|
# it may have some bonus features however, and feedback/testing is welcome
|
||||||
|
|
||||||
docker run -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-cpu:v0.2.2 # CPU, or:
|
docker run -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-cpu:v0.3.0 # CPU, or:
|
||||||
docker run --gpus all -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-gpu:v0.2.2 #NVIDIA GPU
|
docker run --gpus all -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-gpu:v0.3.0 #NVIDIA GPU
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,7 +62,7 @@ docker run --gpus all -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-gpu:v0.2.2 #NV
|
||||||
# *Note for Apple Silicon (M1/M2) users:
|
# *Note for Apple Silicon (M1/M2) users:
|
||||||
# The current GPU build relies on CUDA, which is not supported on Apple Silicon.
|
# The current GPU build relies on CUDA, which is not supported on Apple Silicon.
|
||||||
# If you are on an M1/M2/M3 Mac, please use the `docker/cpu` setup.
|
# If you are on an M1/M2/M3 Mac, please use the `docker/cpu` setup.
|
||||||
# MPS (Apple’s GPU acceleration) support is planned but not yet available.
|
# MPS (Apple's GPU acceleration) support is planned but not yet available.
|
||||||
|
|
||||||
# Models will auto-download, but if needed you can manually download:
|
# Models will auto-download, but if needed you can manually download:
|
||||||
python docker/scripts/download_model.py --output api/src/models/v1_0
|
python docker/scripts/download_model.py --output api/src/models/v1_0
|
||||||
|
@ -139,8 +135,8 @@ with client.audio.speech.with_streaming_response.create(
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>OpenAI-Compatible Speech Endpoint</summary>
|
<summary>OpenAI-Compatible Speech Endpoint</summary>
|
||||||
|
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
v0.2.1
|
0.3.0
|
||||||
|
|
|
@ -2,8 +2,8 @@ apiVersion: v2
|
||||||
name: kokoro-fastapi
|
name: kokoro-fastapi
|
||||||
description: A Helm chart for deploying the Kokoro FastAPI TTS service to Kubernetes
|
description: A Helm chart for deploying the Kokoro FastAPI TTS service to Kubernetes
|
||||||
type: application
|
type: application
|
||||||
version: 0.2.0
|
version: 0.3.0
|
||||||
appVersion: "0.2.0"
|
appVersion: "0.3.0"
|
||||||
|
|
||||||
keywords:
|
keywords:
|
||||||
- tts
|
- tts
|
||||||
|
|
|
@ -20,7 +20,7 @@ services:
|
||||||
|
|
||||||
# # Gradio UI service [Comment out everything below if you don't need it]
|
# # Gradio UI service [Comment out everything below if you don't need it]
|
||||||
# gradio-ui:
|
# gradio-ui:
|
||||||
# image: ghcr.io/remsky/kokoro-fastapi-ui:v0.2.0
|
# image: ghcr.io/remsky/kokoro-fastapi-ui:v${VERSION}
|
||||||
# # Uncomment below (and comment out above) to build from source instead of using the released image
|
# # Uncomment below (and comment out above) to build from source instead of using the released image
|
||||||
# build:
|
# build:
|
||||||
# context: ../../ui
|
# context: ../../ui
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
name: kokoro-tts-gpu
|
name: kokoro-tts-gpu
|
||||||
services:
|
services:
|
||||||
kokoro-tts:
|
kokoro-tts:
|
||||||
# image: ghcr.io/remsky/kokoro-fastapi-gpu:v0.2.0
|
# image: ghcr.io/remsky/kokoro-fastapi-gpu:v${VERSION}
|
||||||
build:
|
build:
|
||||||
context: ../..
|
context: ../..
|
||||||
dockerfile: docker/gpu/Dockerfile
|
dockerfile: docker/gpu/Dockerfile
|
||||||
|
@ -24,7 +24,7 @@ services:
|
||||||
|
|
||||||
# # Gradio UI service
|
# # Gradio UI service
|
||||||
# gradio-ui:
|
# gradio-ui:
|
||||||
# image: ghcr.io/remsky/kokoro-fastapi-ui:v0.2.0
|
# image: ghcr.io/remsky/kokoro-fastapi-ui:v${VERSION}
|
||||||
# # Uncomment below to build from source instead of using the released image
|
# # Uncomment below to build from source instead of using the released image
|
||||||
# # build:
|
# # build:
|
||||||
# # context: ../../ui
|
# # context: ../../ui
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[project]
|
[project]
|
||||||
name = "kokoro-fastapi"
|
name = "kokoro-fastapi"
|
||||||
version = "0.1.4"
|
version = "0.3.0"
|
||||||
description = "FastAPI TTS Service"
|
description = "FastAPI TTS Service"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
|
@ -31,10 +31,11 @@ dependencies = [
|
||||||
"matplotlib>=3.10.0",
|
"matplotlib>=3.10.0",
|
||||||
"mutagen>=1.47.0",
|
"mutagen>=1.47.0",
|
||||||
"psutil>=6.1.1",
|
"psutil>=6.1.1",
|
||||||
"kokoro @ git+https://github.com/hexgrad/kokoro.git@31a2b6337b8c1b1418ef68c48142328f640da938",
|
"espeakng-loader==0.2.4",
|
||||||
'misaki[en,ja,ko,zh] @ git+https://github.com/hexgrad/misaki.git@ebc76c21b66c5fc4866ed0ec234047177b396170',
|
"kokoro==0.9.2",
|
||||||
"spacy==3.7.2",
|
"misaki[en,ja,ko,zh]==0.9.3",
|
||||||
"en-core-web-sm @ https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.7.1/en_core_web_sm-3.7.1-py3-none-any.whl",
|
"spacy==3.8.5",
|
||||||
|
"en-core-web-sm @ https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.8.0/en_core_web_sm-3.8.0-py3-none-any.whl",
|
||||||
"inflect>=7.5.0",
|
"inflect>=7.5.0",
|
||||||
"phonemizer-fork>=3.3.2",
|
"phonemizer-fork>=3.3.2",
|
||||||
"av>=14.2.0",
|
"av>=14.2.0",
|
||||||
|
@ -53,8 +54,8 @@ test = [
|
||||||
"pytest-cov==6.0.0",
|
"pytest-cov==6.0.0",
|
||||||
"httpx==0.26.0",
|
"httpx==0.26.0",
|
||||||
"pytest-asyncio==0.25.3",
|
"pytest-asyncio==0.25.3",
|
||||||
"openai>=1.59.6",
|
|
||||||
"tomli>=2.0.1",
|
"tomli>=2.0.1",
|
||||||
|
"jinja2>=3.1.6"
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.uv]
|
[tool.uv]
|
||||||
|
|
11
readme-parts/config.yaml
Normal file
11
readme-parts/config.yaml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# README Configuration
|
||||||
|
# version is now automatically loaded from the VERSION file
|
||||||
|
tests_passed: "69"
|
||||||
|
coverage: "52"
|
||||||
|
kokoro_version: "0.7.9"
|
||||||
|
kokoro_commit: "31a2b63"
|
||||||
|
misaki_version: "0.7.9"
|
||||||
|
misaki_commit: "ebc76c2"
|
||||||
|
model_version: "1.0"
|
||||||
|
model_commit: "9901c2b"
|
||||||
|
model_commit_full: "9901c2b79161b6e898b7ea857ae5298f47b8b0d6"
|
45
scripts/fix_misaki.py
Normal file
45
scripts/fix_misaki.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
"""
|
||||||
|
Patch for misaki package to fix the EspeakWrapper.set_data_path issue.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import importlib.util
|
||||||
|
|
||||||
|
# Find the misaki package
|
||||||
|
try:
|
||||||
|
import misaki
|
||||||
|
misaki_path = os.path.dirname(misaki.__file__)
|
||||||
|
print(f"Found misaki package at: {misaki_path}")
|
||||||
|
except ImportError:
|
||||||
|
print("Misaki package not found. Make sure it's installed.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Path to the espeak.py file
|
||||||
|
espeak_file = os.path.join(misaki_path, "espeak.py")
|
||||||
|
|
||||||
|
if not os.path.exists(espeak_file):
|
||||||
|
print(f"Could not find {espeak_file}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Read the current content
|
||||||
|
with open(espeak_file, 'r') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
# Check if the problematic line exists
|
||||||
|
if "EspeakWrapper.set_data_path(espeakng_loader.get_data_path())" in content:
|
||||||
|
# Replace the problematic line
|
||||||
|
new_content = content.replace(
|
||||||
|
"EspeakWrapper.set_data_path(espeakng_loader.get_data_path())",
|
||||||
|
"# Fixed line to use data_path attribute instead of set_data_path method\n"
|
||||||
|
"EspeakWrapper.data_path = espeakng_loader.get_data_path()"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Write the modified content back
|
||||||
|
with open(espeak_file, 'w') as f:
|
||||||
|
f.write(new_content)
|
||||||
|
|
||||||
|
print(f"Successfully patched {espeak_file}")
|
||||||
|
else:
|
||||||
|
print(f"The problematic line was not found in {espeak_file}")
|
||||||
|
print("The file may have already been patched or the issue is different.")
|
|
@ -4,40 +4,37 @@ import tomli
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
def extract_dependency_info():
|
def extract_dependency_info():
|
||||||
"""Extract version and commit hash for kokoro and misaki from pyproject.toml"""
|
"""Extract version for kokoro and misaki from pyproject.toml"""
|
||||||
with open("pyproject.toml", "rb") as f:
|
with open("pyproject.toml", "rb") as f:
|
||||||
pyproject = tomli.load(f)
|
pyproject = tomli.load(f)
|
||||||
|
|
||||||
deps = pyproject["project"]["dependencies"]
|
deps = pyproject["project"]["dependencies"]
|
||||||
info = {}
|
info = {}
|
||||||
|
kokoro_found = False
|
||||||
|
misaki_found = False
|
||||||
|
|
||||||
# Extract kokoro info
|
|
||||||
for dep in deps:
|
for dep in deps:
|
||||||
if dep.startswith("kokoro @"):
|
# Match kokoro==version
|
||||||
# Extract version from the dependency string if available
|
kokoro_match = re.match(r"^kokoro==(.+)$", dep)
|
||||||
version_match = re.search(r"kokoro @ git\+https://github\.com/hexgrad/kokoro\.git@", dep)
|
if kokoro_match:
|
||||||
if version_match:
|
info["kokoro"] = {"version": kokoro_match.group(1)}
|
||||||
# If no explicit version, use v0.7.9 as shown in the README
|
kokoro_found = True
|
||||||
version = "v0.7.9"
|
|
||||||
commit_match = re.search(r"@([a-f0-9]{7})", dep)
|
# Match misaki[...] ==version or misaki==version
|
||||||
if commit_match:
|
misaki_match = re.match(r"^misaki(?:\[.*?\])?==(.+)$", dep)
|
||||||
info["kokoro"] = {
|
if misaki_match:
|
||||||
"version": version,
|
info["misaki"] = {"version": misaki_match.group(1)}
|
||||||
"commit": commit_match.group(1)
|
misaki_found = True
|
||||||
}
|
|
||||||
elif dep.startswith("misaki["):
|
# Stop if both found
|
||||||
# Extract version from the dependency string if available
|
if kokoro_found and misaki_found:
|
||||||
version_match = re.search(r"misaki\[.*?\] @ git\+https://github\.com/hexgrad/misaki\.git@", dep)
|
break
|
||||||
if version_match:
|
|
||||||
# If no explicit version, use v0.7.9 as shown in the README
|
if not kokoro_found:
|
||||||
version = "v0.7.9"
|
raise ValueError("Kokoro version not found in pyproject.toml dependencies")
|
||||||
commit_match = re.search(r"@([a-f0-9]{7})", dep)
|
if not misaki_found:
|
||||||
if commit_match:
|
raise ValueError("Misaki version not found in pyproject.toml dependencies")
|
||||||
info["misaki"] = {
|
|
||||||
"version": version,
|
|
||||||
"commit": commit_match.group(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return info
|
return info
|
||||||
|
|
||||||
def run_pytest_with_coverage():
|
def run_pytest_with_coverage():
|
||||||
|
@ -98,20 +95,24 @@ def update_readme_badges(passed_tests, coverage_percentage, dep_info):
|
||||||
|
|
||||||
# Update kokoro badge
|
# Update kokoro badge
|
||||||
if "kokoro" in dep_info:
|
if "kokoro" in dep_info:
|
||||||
|
# Find badge like kokoro-v0.9.2::abcdefg-BB5420 or kokoro-v0.9.2-BB5420
|
||||||
|
kokoro_version = dep_info["kokoro"]["version"]
|
||||||
content = re.sub(
|
content = re.sub(
|
||||||
r'!\[Kokoro\]\(https://img\.shields\.io/badge/kokoro-[^)]+\)',
|
r'(!\[Kokoro\]\(https://img\.shields\.io/badge/kokoro-)[^)-]+(-BB5420\))',
|
||||||
f'',
|
lambda m: f"{m.group(1)}{kokoro_version}{m.group(2)}",
|
||||||
content
|
content
|
||||||
)
|
)
|
||||||
|
|
||||||
# Update misaki badge
|
# Update misaki badge
|
||||||
if "misaki" in dep_info:
|
if "misaki" in dep_info:
|
||||||
|
# Find badge like misaki-v0.9.3::abcdefg-B8860B or misaki-v0.9.3-B8860B
|
||||||
|
misaki_version = dep_info["misaki"]["version"]
|
||||||
content = re.sub(
|
content = re.sub(
|
||||||
r'!\[Misaki\]\(https://img\.shields\.io/badge/misaki-[^)]+\)',
|
r'(!\[Misaki\]\(https://img\.shields\.io/badge/misaki-)[^)-]+(-B8860B\))',
|
||||||
f'',
|
lambda m: f"{m.group(1)}{misaki_version}{m.group(2)}",
|
||||||
content
|
content
|
||||||
)
|
)
|
||||||
|
|
||||||
readme_path.write_text(content)
|
readme_path.write_text(content)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -128,11 +129,11 @@ def main():
|
||||||
print(f"- Tests: {passed_tests} passed")
|
print(f"- Tests: {passed_tests} passed")
|
||||||
print(f"- Coverage: {coverage_percentage}%")
|
print(f"- Coverage: {coverage_percentage}%")
|
||||||
if "kokoro" in dep_info:
|
if "kokoro" in dep_info:
|
||||||
print(f"- Kokoro: {dep_info['kokoro']['version']}::{dep_info['kokoro']['commit']}")
|
print(f"- Kokoro: {dep_info['kokoro']['version']}")
|
||||||
if "misaki" in dep_info:
|
if "misaki" in dep_info:
|
||||||
print(f"- Misaki: {dep_info['misaki']['version']}::{dep_info['misaki']['commit']}")
|
print(f"- Misaki: {dep_info['misaki']['version']}")
|
||||||
else:
|
else:
|
||||||
print("Failed to update badges")
|
print("Failed to update badges")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
195
scripts/update_version.py
Executable file
195
scripts/update_version.py
Executable file
|
@ -0,0 +1,195 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Version Update Script
|
||||||
|
|
||||||
|
This script reads the version from the VERSION file and updates references
|
||||||
|
in pyproject.toml, the Helm chart, and README.md.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
import yaml
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Get the project root directory
|
||||||
|
ROOT_DIR = Path(__file__).parent.parent
|
||||||
|
|
||||||
|
# --- Configuration ---
|
||||||
|
VERSION_FILE = ROOT_DIR / "VERSION"
|
||||||
|
PYPROJECT_FILE = ROOT_DIR / "pyproject.toml"
|
||||||
|
HELM_CHART_FILE = ROOT_DIR / "charts" / "kokoro-fastapi" / "Chart.yaml"
|
||||||
|
README_FILE = ROOT_DIR / "README.md"
|
||||||
|
# --- End Configuration ---
|
||||||
|
|
||||||
|
def update_pyproject(version: str):
|
||||||
|
"""Updates the version in pyproject.toml"""
|
||||||
|
if not PYPROJECT_FILE.exists():
|
||||||
|
print(f"Skipping: {PYPROJECT_FILE} not found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
content = PYPROJECT_FILE.read_text()
|
||||||
|
# Regex to find and capture current version = "X.Y.Z" under [project]
|
||||||
|
pattern = r'(^\[project\]\s*(?:.*\s)*?version\s*=\s*)"([^"]+)"'
|
||||||
|
match = re.search(pattern, content, flags=re.MULTILINE)
|
||||||
|
|
||||||
|
if not match:
|
||||||
|
print(f"Warning: Version pattern not found in {PYPROJECT_FILE}")
|
||||||
|
return
|
||||||
|
|
||||||
|
current_version = match.group(2)
|
||||||
|
if current_version == version:
|
||||||
|
print(f"Already up-to-date: {PYPROJECT_FILE} (version {version})")
|
||||||
|
else:
|
||||||
|
# Perform replacement
|
||||||
|
new_content = re.sub(pattern, rf'\1"{version}"', content, count=1, flags=re.MULTILINE)
|
||||||
|
PYPROJECT_FILE.write_text(new_content)
|
||||||
|
print(f"Updated {PYPROJECT_FILE} from {current_version} to {version}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error processing {PYPROJECT_FILE}: {e}")
|
||||||
|
|
||||||
|
def update_helm_chart(version: str):
|
||||||
|
"""Updates the version and appVersion in the Helm chart"""
|
||||||
|
if not HELM_CHART_FILE.exists():
|
||||||
|
print(f"Skipping: {HELM_CHART_FILE} not found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
content = HELM_CHART_FILE.read_text()
|
||||||
|
original_content = content
|
||||||
|
updated_count = 0
|
||||||
|
|
||||||
|
# Update 'version:' line (unquoted)
|
||||||
|
# Looks for 'version:' followed by optional whitespace and the version number
|
||||||
|
version_pattern = r"^(version:\s*)(\S+)"
|
||||||
|
current_version_match = re.search(version_pattern, content, flags=re.MULTILINE)
|
||||||
|
if current_version_match and current_version_match.group(2) != version:
|
||||||
|
content = re.sub(version_pattern, rf"\g<1>{version}", content, count=1, flags=re.MULTILINE)
|
||||||
|
print(f"Updating 'version' in {HELM_CHART_FILE} from {current_version_match.group(2)} to {version}")
|
||||||
|
updated_count += 1
|
||||||
|
elif current_version_match:
|
||||||
|
print(f"Already up-to-date: 'version' in {HELM_CHART_FILE} is {version}")
|
||||||
|
else:
|
||||||
|
print(f"Warning: 'version:' pattern not found in {HELM_CHART_FILE}")
|
||||||
|
|
||||||
|
|
||||||
|
# Update 'appVersion:' line (quoted or unquoted)
|
||||||
|
# Looks for 'appVersion:' followed by optional whitespace, optional quote, the version, optional quote
|
||||||
|
app_version_pattern = r"^(appVersion:\s*)(\"?)([^\"\s]+)(\"?)"
|
||||||
|
current_app_version_match = re.search(app_version_pattern, content, flags=re.MULTILINE)
|
||||||
|
|
||||||
|
if current_app_version_match:
|
||||||
|
leading_whitespace = current_app_version_match.group(1) # e.g., "appVersion: "
|
||||||
|
opening_quote = current_app_version_match.group(2) # e.g., '"' or ''
|
||||||
|
current_app_ver = current_app_version_match.group(3) # e.g., '0.2.0'
|
||||||
|
closing_quote = current_app_version_match.group(4) # e.g., '"' or ''
|
||||||
|
|
||||||
|
# Check if quotes were consistent (both present or both absent)
|
||||||
|
if opening_quote != closing_quote:
|
||||||
|
print(f"Warning: Inconsistent quotes found for appVersion in {HELM_CHART_FILE}. Skipping update for this line.")
|
||||||
|
elif current_app_ver == version and opening_quote == '"': # Check if already correct *and* quoted
|
||||||
|
print(f"Already up-to-date: 'appVersion' in {HELM_CHART_FILE} is \"{version}\"")
|
||||||
|
else:
|
||||||
|
# Always replace with the quoted version
|
||||||
|
replacement = f'{leading_whitespace}"{version}"' # Ensure quotes
|
||||||
|
original_display = f"{opening_quote}{current_app_ver}{closing_quote}" # How it looked before
|
||||||
|
target_display = f'"{version}"' # How it should look
|
||||||
|
|
||||||
|
# Only report update if the displayed value actually changes
|
||||||
|
if original_display != target_display:
|
||||||
|
content = re.sub(app_version_pattern, replacement, content, count=1, flags=re.MULTILINE)
|
||||||
|
print(f"Updating 'appVersion' in {HELM_CHART_FILE} from {original_display} to {target_display}")
|
||||||
|
updated_count += 1
|
||||||
|
else:
|
||||||
|
# It matches the target version but might need quoting fixed silently if we didn't update
|
||||||
|
# Or it was already correct. Check if content changed. If not, report up-to-date.
|
||||||
|
if not (content != original_content and updated_count > 0): # Avoid double message if version also changed
|
||||||
|
print(f"Already up-to-date: 'appVersion' in {HELM_CHART_FILE} is {target_display}")
|
||||||
|
|
||||||
|
|
||||||
|
else:
|
||||||
|
print(f"Warning: 'appVersion:' pattern not found in {HELM_CHART_FILE}")
|
||||||
|
|
||||||
|
|
||||||
|
# Write back only if changes were made
|
||||||
|
if content != original_content:
|
||||||
|
HELM_CHART_FILE.write_text(content)
|
||||||
|
# Confirmation message printed above during the specific update
|
||||||
|
elif updated_count == 0 and current_version_match and current_app_version_match :
|
||||||
|
# If no updates were made but patterns were found, confirm it's up-to-date overall
|
||||||
|
print(f"Already up-to-date: {HELM_CHART_FILE} (version {version})")
|
||||||
|
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error processing {HELM_CHART_FILE}: {e}")
|
||||||
|
|
||||||
|
def update_readme(version_with_v: str):
|
||||||
|
"""Updates Docker image tags in README.md"""
|
||||||
|
if not README_FILE.exists():
|
||||||
|
print(f"Skipping: {README_FILE} not found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
content = README_FILE.read_text()
|
||||||
|
# Regex to find and capture current ghcr.io/.../kokoro-fastapi-(cpu|gpu):vX.Y.Z
|
||||||
|
pattern = r'(ghcr\.io/remsky/kokoro-fastapi-(?:cpu|gpu)):(v\d+\.\d+\.\d+)'
|
||||||
|
matches = list(re.finditer(pattern, content)) # Find all occurrences
|
||||||
|
|
||||||
|
if not matches:
|
||||||
|
print(f"Warning: Docker image tag pattern not found in {README_FILE}")
|
||||||
|
else:
|
||||||
|
updated_needed = False
|
||||||
|
for match in matches:
|
||||||
|
current_tag = match.group(2)
|
||||||
|
if current_tag != version_with_v:
|
||||||
|
updated_needed = True
|
||||||
|
break # Only need one mismatch to trigger update
|
||||||
|
|
||||||
|
if updated_needed:
|
||||||
|
# Perform replacement on all occurrences
|
||||||
|
new_content = re.sub(pattern, rf'\1:{version_with_v}', content)
|
||||||
|
README_FILE.write_text(new_content)
|
||||||
|
print(f"Updated Docker image tags in {README_FILE} to {version_with_v}")
|
||||||
|
else:
|
||||||
|
print(f"Already up-to-date: Docker image tags in {README_FILE} (version {version_with_v})")
|
||||||
|
|
||||||
|
# Check for ':latest' tag usage remains the same
|
||||||
|
if ':latest' in content:
|
||||||
|
print(f"Warning: Found ':latest' tag in {README_FILE}. Consider updating manually if needed.")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error processing {README_FILE}: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Read the version from the VERSION file
|
||||||
|
if not VERSION_FILE.exists():
|
||||||
|
print(f"Error: {VERSION_FILE} not found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
version = VERSION_FILE.read_text().strip()
|
||||||
|
if not re.match(r"^\d+\.\d+\.\d+$", version):
|
||||||
|
print(f"Error: Invalid version format '{version}' in {VERSION_FILE}. Expected X.Y.Z")
|
||||||
|
return
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error reading {VERSION_FILE}: {e}")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"Read version: {version} from {VERSION_FILE}")
|
||||||
|
print("-" * 20)
|
||||||
|
|
||||||
|
# Prepare versions (with and without 'v')
|
||||||
|
version_plain = version
|
||||||
|
version_with_v = f"v{version}"
|
||||||
|
|
||||||
|
# Update files
|
||||||
|
update_pyproject(version_plain)
|
||||||
|
update_helm_chart(version_plain)
|
||||||
|
update_readme(version_with_v)
|
||||||
|
|
||||||
|
print("-" * 20)
|
||||||
|
print("Version update script finished.")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -1,49 +0,0 @@
|
||||||
{
|
|
||||||
"document": "doc.report.command",
|
|
||||||
"version": "ov/command/slim/1.1",
|
|
||||||
"engine": "linux/amd64|ALP|x.1.42.2|29e62e7836de7b1004607c51c502537ffe1969f0|2025-01-16_07:48:54AM|x",
|
|
||||||
"containerized": false,
|
|
||||||
"host_distro": {
|
|
||||||
"name": "Ubuntu",
|
|
||||||
"version": "22.04",
|
|
||||||
"display_name": "Ubuntu 22.04.5 LTS"
|
|
||||||
},
|
|
||||||
"type": "slim",
|
|
||||||
"state": "error",
|
|
||||||
"target_reference": "kokoro-fastapi:latest",
|
|
||||||
"system": {
|
|
||||||
"type": "",
|
|
||||||
"release": "",
|
|
||||||
"distro": {
|
|
||||||
"name": "",
|
|
||||||
"version": "",
|
|
||||||
"display_name": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"source_image": {
|
|
||||||
"identity": {
|
|
||||||
"id": ""
|
|
||||||
},
|
|
||||||
"size": 0,
|
|
||||||
"size_human": "",
|
|
||||||
"create_time": "",
|
|
||||||
"architecture": "",
|
|
||||||
"container_entry": {
|
|
||||||
"exe_path": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"minified_image_size": 0,
|
|
||||||
"minified_image_size_human": "",
|
|
||||||
"minified_image": "",
|
|
||||||
"minified_image_id": "",
|
|
||||||
"minified_image_digest": "",
|
|
||||||
"minified_image_has_data": false,
|
|
||||||
"minified_by": 0,
|
|
||||||
"artifact_location": "",
|
|
||||||
"container_report_name": "",
|
|
||||||
"seccomp_profile_name": "",
|
|
||||||
"apparmor_profile_name": "",
|
|
||||||
"image_stack": null,
|
|
||||||
"image_created": false,
|
|
||||||
"image_build_engine": ""
|
|
||||||
}
|
|
|
@ -10,9 +10,17 @@ export PYTHONPATH=$PROJECT_ROOT:$PROJECT_ROOT/api
|
||||||
export MODEL_DIR=src/models
|
export MODEL_DIR=src/models
|
||||||
export VOICES_DIR=src/voices/v1_0
|
export VOICES_DIR=src/voices/v1_0
|
||||||
export WEB_PLAYER_PATH=$PROJECT_ROOT/web
|
export WEB_PLAYER_PATH=$PROJECT_ROOT/web
|
||||||
|
# Set the espeak-ng data path to your location
|
||||||
|
export ESPEAK_DATA_PATH=/usr/lib/x86_64-linux-gnu/espeak-ng-data
|
||||||
|
|
||||||
# Run FastAPI with CPU extras using uv run
|
# Run FastAPI with CPU extras using uv run
|
||||||
# Note: espeak may still require manual installation,
|
# Note: espeak may still require manual installation,
|
||||||
uv pip install -e ".[cpu]"
|
uv pip install -e ".[cpu]"
|
||||||
uv run --no-sync python docker/scripts/download_model.py --output api/src/models/v1_0
|
uv run --no-sync python docker/scripts/download_model.py --output api/src/models/v1_0
|
||||||
|
|
||||||
|
# Apply the misaki patch to fix possible EspeakWrapper issue in older versions
|
||||||
|
# echo "Applying misaki patch..."
|
||||||
|
# python scripts/fix_misaki.py
|
||||||
|
|
||||||
|
# Start the server
|
||||||
uv run --no-sync uvicorn api.src.main:app --host 0.0.0.0 --port 8880
|
uv run --no-sync uvicorn api.src.main:app --host 0.0.0.0 --port 8880
|
||||||
|
|
Loading…
Add table
Reference in a new issue