GPT-SoVITS/only_tts/download_models.py
2025-09-05 08:10:39 +09:00

299 lines
11 KiB
Python

#!/usr/bin/env python3
"""
GPT-SoVITS only_tts 모델 다운로드 및 설치 스크립트
V4 및 V2Pro 시리즈 모델들을 자동으로 다운로드하고 설치합니다.
Usage:
python download_models.py --all
python download_models.py --v4
python download_models.py --v2pro
python download_models.py --base-models
"""
import os
import sys
import argparse
import subprocess
import shutil
from pathlib import Path
import requests
from tqdm import tqdm
import zipfile
import hashlib
# 현재 스크립트 위치 기준으로 pretrained_models 경로 설정
SCRIPT_DIR = Path(__file__).parent
PRETRAINED_DIR = SCRIPT_DIR / "pretrained_models"
# 모델 다운로드 정보
MODEL_CONFIGS = {
"base_models": {
"chinese-hubert-base": {
"url": "https://huggingface.co/lj1995/GPT-SoVITS/resolve/main/chinese-hubert-base.zip",
"path": PRETRAINED_DIR / "chinese-hubert-base",
"description": "Multi-language HuBERT base model (한국어/영어 필수 - 다국어 음성 특징 추출)"
},
"chinese-roberta-wwm-ext-large": {
"url": "https://huggingface.co/lj1995/GPT-SoVITS/resolve/main/chinese-roberta-wwm-ext-large.zip",
"path": PRETRAINED_DIR / "chinese-roberta-wwm-ext-large",
"description": "Multi-language RoBERTa model (한국어/영어 필수 - 다국어 텍스트 특징 추출)"
}
},
"v4_models": {
"s1bert25hz-2kh-longer-epoch=68e-step=50232.ckpt": {
"url": "https://huggingface.co/lj1995/GPT-SoVITS/resolve/main/gsv-v4-pretrained/s1bert25hz-2kh-longer-epoch=68e-step=50232.ckpt",
"path": PRETRAINED_DIR / "gsv-v4-pretrained" / "s1bert25hz-2kh-longer-epoch=68e-step=50232.ckpt",
"description": "V4 GPT model checkpoint"
},
"s2Gv4.pth": {
"url": "https://huggingface.co/lj1995/GPT-SoVITS/resolve/main/gsv-v4-pretrained/s2Gv4.pth",
"path": PRETRAINED_DIR / "gsv-v4-pretrained" / "s2Gv4.pth",
"description": "V4 SoVITS model"
},
"vocoder.pth": {
"url": "https://huggingface.co/lj1995/GPT-SoVITS/resolve/main/gsv-v4-pretrained/vocoder.pth",
"path": PRETRAINED_DIR / "gsv-v4-pretrained" / "vocoder.pth",
"description": "V4 Vocoder model"
}
},
"v2pro_models": {
"s1bert25hz-5kh-longer-epoch=12-step=369668.ckpt": {
"url": "https://huggingface.co/lj1995/GPT-SoVITS/resolve/main/v2Pro/s1bert25hz-5kh-longer-epoch=12-step=369668.ckpt",
"path": PRETRAINED_DIR / "v2Pro" / "s1bert25hz-5kh-longer-epoch=12-step=369668.ckpt",
"description": "V2Pro GPT model checkpoint"
},
"s2Gv2Pro.pth": {
"url": "https://huggingface.co/lj1995/GPT-SoVITS/resolve/main/v2Pro/s2Gv2Pro.pth",
"path": PRETRAINED_DIR / "v2Pro" / "s2Gv2Pro.pth",
"description": "V2Pro SoVITS model"
},
"s2Gv2ProPlus.pth": {
"url": "https://huggingface.co/lj1995/GPT-SoVITS/resolve/main/v2Pro/s2Gv2ProPlus.pth",
"path": PRETRAINED_DIR / "v2Pro" / "s2Gv2ProPlus.pth",
"description": "V2ProPlus SoVITS model"
},
"pretrained_eres2netv2w24s4ep4.ckpt": {
"url": "https://huggingface.co/lj1995/GPT-SoVITS/resolve/main/sv/pretrained_eres2netv2w24s4ep4.ckpt",
"path": PRETRAINED_DIR / "sv" / "pretrained_eres2netv2w24s4ep4.ckpt",
"description": "Speaker Verification model (V2Pro 필수)"
}
}
}
def download_file(url: str, filepath: Path, description: str = ""):
"""파일 다운로드 (진행률 표시)"""
try:
# HEAD 요청으로 파일 크기 확인
response = requests.head(url, allow_redirects=True)
total_size = int(response.headers.get('content-length', 0))
# 디렉토리 생성
filepath.parent.mkdir(parents=True, exist_ok=True)
# 파일 다운로드
response = requests.get(url, stream=True)
response.raise_for_status()
with open(filepath, 'wb') as f:
with tqdm(
desc=f"Downloading {description or filepath.name}",
total=total_size,
unit='B',
unit_scale=True,
unit_divisor=1024,
) as pbar:
for chunk in response.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
pbar.update(len(chunk))
print(f"✅ Downloaded: {filepath}")
return True
except Exception as e:
print(f"❌ Failed to download {url}: {e}")
return False
def check_file_exists(filepath: Path) -> bool:
"""파일 존재 여부 확인"""
return filepath.exists() and filepath.stat().st_size > 0
def download_models(model_groups: list, force: bool = False):
"""모델 다운로드"""
print(f"🚀 GPT-SoVITS only_tts 모델 다운로드 시작")
print(f"📁 설치 경로: {PRETRAINED_DIR.absolute()}")
total_files = 0
downloaded_files = 0
skipped_files = 0
for group in model_groups:
if group not in MODEL_CONFIGS:
print(f"⚠️ 알 수 없는 모델 그룹: {group}")
continue
print(f"\n📦 {group.replace('_', ' ').title()} 다운로드 중...")
models = MODEL_CONFIGS[group]
for model_name, model_info in models.items():
total_files += 1
filepath = model_info["path"]
# 파일이 이미 존재하고 force가 아닌 경우 스킵
if check_file_exists(filepath) and not force:
print(f"⏭️ 이미 존재함: {filepath.name}")
skipped_files += 1
continue
# 다운로드 시도
if download_file(model_info["url"], filepath, model_info["description"]):
downloaded_files += 1
else:
print(f"❌ 다운로드 실패: {model_name}")
# 결과 요약
print(f"\n📊 다운로드 완료!")
print(f" 총 파일: {total_files}")
print(f" 다운로드: {downloaded_files}")
print(f" 스킵: {skipped_files}")
if downloaded_files > 0:
print(f"\n✅ 새로 다운로드된 파일들이 {PRETRAINED_DIR} 에 저장되었습니다.")
def install_git_lfs():
"""Git LFS 설치 확인 및 설치"""
try:
subprocess.run(["git", "lfs", "--version"], check=True, capture_output=True)
print("✅ Git LFS가 이미 설치되어 있습니다.")
return True
except (subprocess.CalledProcessError, FileNotFoundError):
print("⚠️ Git LFS가 설치되어 있지 않습니다.")
# 자동 설치 시도 (Linux/Mac)
if sys.platform != "win32":
try:
if shutil.which("apt-get"): # Ubuntu/Debian
subprocess.run(["sudo", "apt-get", "install", "-y", "git-lfs"], check=True)
elif shutil.which("brew"): # macOS
subprocess.run(["brew", "install", "git-lfs"], check=True)
elif shutil.which("yum"): # CentOS/RHEL
subprocess.run(["sudo", "yum", "install", "-y", "git-lfs"], check=True)
subprocess.run(["git", "lfs", "install"], check=True)
print("✅ Git LFS 설치 완료!")
return True
except subprocess.CalledProcessError:
pass
print("❌ Git LFS를 수동으로 설치해주세요: https://git-lfs.github.io/")
return False
def check_dependencies():
"""의존성 확인"""
print("🔍 의존성 확인 중...")
# Python 패키지 확인
required_packages = ["requests", "tqdm"]
missing_packages = []
for package in required_packages:
try:
__import__(package)
except ImportError:
missing_packages.append(package)
if missing_packages:
print(f"⚠️ 필요한 패키지가 설치되어 있지 않습니다: {', '.join(missing_packages)}")
print(f" 다음 명령어로 설치하세요: pip install {' '.join(missing_packages)}")
return False
print("✅ 의존성 확인 완료!")
return True
def show_model_info():
"""사용 가능한 모델 정보 표시"""
print("📋 사용 가능한 모델들:")
print()
for group_name, models in MODEL_CONFIGS.items():
print(f"🔸 {group_name.replace('_', ' ').title()}:")
for model_name, model_info in models.items():
status = "" if check_file_exists(model_info["path"]) else ""
print(f" {status} {model_name}")
print(f" 📝 {model_info['description']}")
print(f" 📁 {model_info['path']}")
print()
def main():
parser = argparse.ArgumentParser(
description="GPT-SoVITS only_tts 모델 다운로드 및 설치",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
사용 예시:
python download_models.py --all # 모든 모델 다운로드
python download_models.py --v4 # V4 모델만 다운로드
python download_models.py --v2pro # V2Pro 모델만 다운로드
python download_models.py --base-models # 기본 모델만 다운로드
python download_models.py --info # 모델 정보 표시
"""
)
parser.add_argument("--all", action="store_true", help="모든 모델 다운로드")
parser.add_argument("--v4", action="store_true", help="V4 모델 다운로드")
parser.add_argument("--v2pro", action="store_true", help="V2Pro 모델 다운로드")
parser.add_argument("--base-models", action="store_true", help="기본 모델들 다운로드")
parser.add_argument("--force", action="store_true", help="기존 파일 덮어쓰기")
parser.add_argument("--info", action="store_true", help="모델 정보 표시")
args = parser.parse_args()
# 정보 표시
if args.info:
show_model_info()
return
# 의존성 확인
if not check_dependencies():
sys.exit(1)
# 다운로드할 모델 그룹 결정
model_groups = []
if args.all:
model_groups = ["base_models", "v4_models", "v2pro_models"]
else:
if args.base_models:
model_groups.append("base_models")
if args.v4:
model_groups.append("base_models") # V4는 기본 모델 필요
model_groups.append("v4_models")
if args.v2pro:
model_groups.append("base_models") # V2Pro도 기본 모델 필요
model_groups.append("v2pro_models")
# 아무 옵션도 선택하지 않은 경우
if not model_groups:
print("❓ 다운로드할 모델을 선택해주세요.")
print(" --help 옵션으로 사용법을 확인하세요.")
print()
show_model_info()
return
# 중복 제거
model_groups = list(dict.fromkeys(model_groups))
# 모델 다운로드
download_models(model_groups, args.force)
# 설치 완료 메시지
print(f"\n🎉 모델 설치가 완료되었습니다!")
print(f" 이제 tts_simple.py를 사용하여 TTS를 실행할 수 있습니다.")
print()
print("📖 사용 예시:")
print(" from tts_simple import TTSEngine")
print(" tts = TTSEngine(model='v4', device='cuda')")
if __name__ == "__main__":
main()