mirror of
https://github.com/RVC-Boss/GPT-SoVITS.git
synced 2025-09-29 17:10:02 +08:00
299 lines
11 KiB
Python
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()
|