最近在研究語音合成與仿聲技術時,接觸到一個蠻有趣的開源專案 —— GPT-SoVITS。 這是一套結合語音合成與語者轉換的系統,融合了 SoVITS(Soft Voice Conversion with VITS)的聲音轉換技術與語者特徵建模能力,同時加入了類似 GPT 的語音生成邏輯。 簡單來說,它可以將輸入的語音或文字轉換成特定語者的聲音,而且合成品質也相當不錯。 由於它是開源且模組化的架構,不少語音開發者、虛擬角色創作者,甚至是語音應用的愛好者都對這個專案相當感興趣。

本文重點

這篇文章主要分享我使用 Docker 部署 GPT-SoVITS 的過程與心得,但不包含模型訓練流程。 如果你已經完成模型訓練,通常會取得兩個模型權重檔案:GPT_weights 和 SoVITS_weights。目前我整理出三種執行方式:

  • 使用 gpt-sovits-python 套件
    使用 gpt-sovits-python 套件執行似乎是最乾淨的作法,但它需要透過 conda 建立執行環境,對我來說,conda 比較適合開發環境,在正式伺服器上使用我就會比較猶豫。
  • 使用 GPT-SoVITS 提供的 api_v2.py
    GPT-SoVITS 原本就提供了一套 API 程式碼,可以直接讓其他專案串接。問題是,如果直接在伺服器上安裝整個 GPT-SoVITS 環境,會讓系統變得比較混亂、不好維護。
  • 使用 Docker 安裝 GPT-SoVITS (推薦)
    這是我目前採用的方式,基本上就是將第二種方法容器化,透過 Docker 執行 api_v2.py。 這樣可以把 GPT-SoVITS 跟主機系統隔離開來,乾淨又好管理。 以下就會以這個方法為主,分享部署的步驟與遇到的問題。

以下是本文提及的一些重要目錄及檔案:

  • /opt/GPT-SoVITS
    GPT-SoVITS 專案目錄,這是本文假設的路徑,您可以依照自己喜好修改。
  • /opt/GPT-SoVITS/GPT_weights
    訓練好的 GPT_weights 存放目錄。
  • /opt/GPT-SoVITS/SoVITS_weights
    訓練好的 SoVITS_weights 存放目錄。
  • /opt/GPT-SoVITS/reference
    存放 API 會使用到的範例音檔。
  • /opt/GPT-SoVITS/Dockerfile
    建立 Docker 映像檔的 Dockerfile。
  • /opt/GPT-SoVITS/GPT_SoVITS/configs/tts_infer.yaml
    TTS 參數設定。

準備 GPT-SoVITS 專案

  • STEP 1

    下載 GPT-SoVITS 專案

                        
                            cd /opt
                            git clone https://github.com/RVC-Boss/GPT-SoVITS.git
                        
                    
  • STEP 2

    下載預訓練模型,放置到指定路徑,這邊直接依照 github 上的 README 下載即可。

  • STEP 3

    編輯 /opt/GPT-SoVITS/Dockerfile 檔案,參考下方修改行 42 ~ 48 行。

                        
                            # Base CUDA image
                            FROM cnstark/pytorch:2.0.1-py3.9.17-cuda11.8.0-ubuntu20.04
    
                            LABEL maintainer="breakstring@hotmail.com"
                            LABEL version="dev-20240209"
                            LABEL description="Docker image for GPT-SoVITS"
    
    
                            # Install 3rd party apps
                            ENV DEBIAN_FRONTEND=noninteractive
                            ENV TZ=Etc/UTC
                            RUN apt-get update && \
                                apt-get install -y --no-install-recommends tzdata ffmpeg libsox-dev parallel aria2 git git-lfs && \
                                git lfs install && \
                                rm -rf /var/lib/apt/lists/*
    
                            # Copy only requirements.txt initially to leverage Docker cache
                            WORKDIR /workspace
                            COPY requirements.txt /workspace/
                            RUN pip install --no-cache-dir -r requirements.txt
    
                            # Define a build-time argument for image type
                            ARG IMAGE_TYPE=full
    
                            # Conditional logic based on the IMAGE_TYPE argument
                            # Always copy the Docker directory, but only use it if IMAGE_TYPE is not "elite"
                            COPY ./Docker /workspace/Docker
                            # elite 类型的镜像里面不包含额外的模型
                            RUN if [ "$IMAGE_TYPE" != "elite" ]; then \
                                    chmod +x /workspace/Docker/download.sh && \
                                    /workspace/Docker/download.sh && \
                                    python /workspace/Docker/download.py && \
                                    python -m nltk.downloader averaged_perceptron_tagger cmudict; \
                                fi
    
    
                            # Copy the rest of the application
                            COPY . /workspace
    
                            EXPOSE 9871 9872 9873 9874 9880
    
                            # 增加這行,下載分詞庫。
                            # 這行在容器執行時,有需要時程式碼也會自動下載分詞庫,但不知道為什麼都會下載失敗
                            # 這可能與容器內 DNS 設定或防火牆限制有關,因此改為在建置映像時就預先下載相關資源。
                            RUN python -m nltk.downloader averaged_perceptron_tagger_eng
    
                            # 修改這一行,直接執行 api_v2.py
                            CMD ["python", "api_v2.py", "-a", "0.0.0.0", "-p", "9880", "-c", "GPT_SoVITS/configs/tts_infer.yaml"]
                        
                    
  • STEP 4

    編輯 /opt/GPT-SoVITS/GPT_SoVITS/configs/tts_infer.yaml 檔案,只需要修改 custom 中的 t2s_weights_path、vits_weights_path 及 version。

                        
                            custom:
                              bert_base_path: GPT_SoVITS/pretrained_models/chinese-roberta-wwm-ext-large
                              cnhuhbert_base_path: GPT_SoVITS/pretrained_models/chinese-hubert-base
                              device: cuda
                              is_half: true
                              t2s_weights_path: [換成自己訓練好的 GPT_weights 路徑]
                              version: [SoVITS 模型版本]
                              vits_weights_path: [換成自己訓練好的 SoVITS_weights 路徑]
                            v1:
                              bert_base_path: GPT_SoVITS/pretrained_models/chinese-roberta-wwm-ext-large
                              cnhuhbert_base_path: GPT_SoVITS/pretrained_models/chinese-hubert-base
                              device: cpu
                              is_half: false
                              t2s_weights_path: GPT_SoVITS/pretrained_models/s1bert25hz-2kh-longer-epoch=68e-step=50232.ckpt
                              version: v1
                              vits_weights_path: GPT_SoVITS/pretrained_models/s2G488k.pth
                            ... (略過) ...
                        
                    
  • STEP 5

    建立 /opt/GPT-SoVITS/reference 資料夾,並準備 5 ~ 10 秒的範例音檔放在 reference 資料夾底下,假設檔名為 sample.wav,這個在後續 API 會使用到。

建立容器

根據以下指令建立映像檔及容器,容器會使用到 9880 port,後續請記得打開 9880 port。

            
                # 建立映像檔
                docker build . --no-cache -t gptsovits

                # 執行容器
                docker run -d --name gptsovits \
                    --restart=always \
                    -p 9880:9880 \
                    --gpus=all \
                    --env=is_half=False \
                    --shm-size="16G" \
                    --volume=/opt/GPT-SoVITS/output:/workspace/output \
                    --volume=/opt/GPT-SoVITS/logs:/workspace/logs \
                    --volume=/opt/GPT-SoVITS/GPT_weights:/workspace/GPT_weights \
                    --volume=/opt/GPT-SoVITS/SoVITS_weights:/workspace/SoVITS_weights \
                    --volume=/opt/GPT-SoVITS/reference:/workspace/reference \
                    --workdir=/workspace \
                    gptsovits

                # 查看容器中 API Log
                docker logs --follow gptsovits
                
                # 如果正常執行沒問題,您應該可以在終端機看到以下內容
                ---------------------------------------------TTS Config---------------------------------------------
                device              : cuda
                is_half             : True
                version             : v2
                t2s_weights_path    : GPT_SoVITS/pretrained_models/gsv-v2final-pretrained/s1bert25hz-5kh-longer-epoch=12-step=369668.ckpt
                vits_weights_path   : GPT_SoVITS/pretrained_models/gsv-v2final-pretrained/s2G2333k.pth
                bert_base_path      : GPT_SoVITS/pretrained_models/chinese-roberta-wwm-ext-large
                cnhuhbert_base_path : GPT_SoVITS/pretrained_models/chinese-hubert-base
                ----------------------------------------------------------------------------------------------------
                ... (省略)...
                INFO:     Started server process [1]
                INFO:     Waiting for application startup.
                INFO:     Application startup complete.
                INFO:     Uvicorn running on http://0.0.0.0:9880 (Press CTRL+C to quit)
            
        

其他可能會使用到的 docker 指令。

            
                # 停止容器
                docker stop gptsovits

                # 刪除容器
                docker rm gptsovits

                # 刪除映像檔
                docker rmi gptsovits

                # 清除建立映像檔時的快取
                docker builder prune
            
        

測試 API

在瀏覽器輸入 http://localhost:9880/docs,可以查看 FastAPI 開啟的所有 API 資訊,我們可以使用 [GET] /tts 進行測試。重要參數如下:

  • text
    要合成的語音文字。
  • text_lang
    合成語音文字語系代碼,中文填寫 zh,英文填寫 en。
  • ref_audio_path
    參考範例音檔,就是放在 reference 資料夾中的音檔路徑 (/workspace/reference/sample.wav)。
  • prompt_lang
    範例音檔案語系,中文填寫 zh,英文填寫 en。
  • prompt_text
    範例音檔案對應的文字。

除了以上參數,其他都用預設值即可,點選下方的 Execute 按鈕,複製 Request URL 貼到瀏覽器網址列,如果系統架設沒問題的話,就能看到合成的音檔。