File size: 9,584 Bytes
3bfebb6
 
 
 
 
 
 
297dc31
3bfebb6
 
 
 
 
06059a8
297dc31
28df979
4b92fef
297dc31
06059a8
297dc31
3bfebb6
06059a8
297dc31
 
 
 
 
 
 
 
 
 
 
3bfebb6
06059a8
 
95bb127
 
 
 
 
06059a8
95bb127
297dc31
 
95bb127
06059a8
 
 
 
 
 
88ccf2d
06059a8
 
 
88ccf2d
 
06059a8
 
 
88ccf2d
 
06059a8
 
 
88ccf2d
06059a8
 
 
 
88ccf2d
06059a8
 
 
297dc31
06059a8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64ea52e
 
28df979
64ea52e
 
28df979
 
 
 
 
 
 
 
 
 
06059a8
297dc31
 
 
3bfebb6
297dc31
06059a8
 
64ea52e
28df979
 
 
 
 
 
 
 
 
 
06059a8
28df979
297dc31
06059a8
 
 
 
297dc31
06059a8
 
3bfebb6
297dc31
 
 
 
 
 
 
 
 
 
 
 
 
06059a8
297dc31
 
 
06059a8
297dc31
3bfebb6
 
 
 
 
 
 
 
4b92fef
3bfebb6
3dfa434
297dc31
3dfa434
297dc31
 
3dfa434
 
 
 
 
 
 
 
3bfebb6
 
297dc31
3bfebb6
 
297dc31
 
 
3bfebb6
297dc31
3bfebb6
 
 
297dc31
3bfebb6
 
297dc31
3bfebb6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#!/usr/bin/env python3
"""

Model Download Script for MiloMusic

Downloads required model files from Hugging Face Hub at runtime to avoid storage limits.

"""

import os
import subprocess
import shutil
from pathlib import Path


def download_xcodec_models():
    """Download xcodec_mini_infer using git clone (no LFS) + wget for large files"""

    # Base path for xcodec models - convert to absolute path to avoid working directory issues
    xcodec_base = Path("YuE/inference/xcodec_mini_infer").resolve()

    print("πŸ“₯ Downloading xcodec_mini_infer using git clone + wget strategy...")

    try:
        # Remove existing directory if it exists
        if xcodec_base.exists():
            print("πŸ—‘οΈ Removing existing xcodec_mini_infer directory...")
            shutil.rmtree(xcodec_base)

        # Ensure parent directory exists
        os.makedirs(xcodec_base.parent, exist_ok=True)

        # Change to the parent directory for git clone
        original_cwd = os.getcwd()
        os.chdir(xcodec_base.parent)

        try:
            # Step 1: Clone repository structure without LFS files
            print("πŸ”„ Step 1: Cloning repository structure (no LFS)...")

            # Set environment variable to skip LFS files during clone
            env = os.environ.copy()
            env["GIT_LFS_SKIP_SMUDGE"] = "1"

            subprocess.run([
                "git", "clone",
                "https://huggingface.co/m-a-p/xcodec_mini_infer",
                "xcodec_mini_infer"
            ], check=True, capture_output=True, text=True, timeout=300, env=env)

            print("βœ… Repository structure downloaded successfully")

            # Step 2: Download critical LFS files using wget
            print("πŸ”„ Step 2: Downloading critical LFS files with wget...")

            # Define critical LFS files and their download URLs
            lfs_files = [
                {
                    "path": "decoders/decoder_131000.pth",
                    "url": "https://huggingface.co/m-a-p/xcodec_mini_infer/resolve/main/decoders/decoder_131000.pth",
                    "description": "Vocal decoder model (70MB)"
                },
                {
                    "path": "decoders/decoder_151000.pth",
                    "url": "https://huggingface.co/m-a-p/xcodec_mini_infer/resolve/main/decoders/decoder_151000.pth",
                    "description": "Instrumental decoder model (70MB)"
                },
                {
                    "path": "final_ckpt/ckpt_00360000.pth",
                    "url": "https://huggingface.co/m-a-p/xcodec_mini_infer/resolve/main/final_ckpt/ckpt_00360000.pth",
                    "description": "Main checkpoint (1.3GB)"
                },
                {
                    "path": "semantic_ckpts/hf_1_325000/pytorch_model.bin",
                    "url": "https://huggingface.co/m-a-p/xcodec_mini_infer/resolve/main/semantic_ckpts/hf_1_325000/pytorch_model.bin",
                    "description": "Semantic model (361MB)"
                }
            ]

            # Change to the cloned directory
            os.chdir("xcodec_mini_infer")

            # Download each LFS file
            success_count = 0
            for file_info in lfs_files:
                try:
                    file_path = Path(file_info["path"])
                    print(f"πŸ“₯ Downloading {file_info['description']}...")

                    # Ensure directory exists
                    os.makedirs(file_path.parent, exist_ok=True)

                    # Download with wget
                    subprocess.run([
                        "wget", "-O", str(file_path),
                        file_info["url"]
                    ], check=True, capture_output=True, text=True, timeout=1800)  # 30min timeout for large files

                    # Verify download
                    if file_path.exists() and file_path.stat().st_size > 1024:  # > 1KB
                        print(f"βœ… Successfully downloaded {file_info['path']} ({file_path.stat().st_size // (1024*1024)}MB)")
                        success_count += 1
                    else:
                        print(f"⚠️ {file_info['path']} download appears incomplete")

                except subprocess.CalledProcessError as e:
                    print(f"❌ Failed to download {file_info['path']}: {e}")
                    if e.stderr:
                        print(f"Error details: {e.stderr[-500:]}...")  # Last 500 chars
                except subprocess.TimeoutExpired:
                    print(f"❌ Download timeout for {file_info['path']} (large file)")
                except Exception as e:
                    print(f"❌ Unexpected error downloading {file_info['path']}: {e}")

            os.chdir("..")

            # Debug: Print current working directory and file locations
            print(f"πŸ” Current working directory: {os.getcwd()}")
            print(f"πŸ” Expected xcodec_base (absolute): {xcodec_base}")
            print(f"πŸ” xcodec_base exists: {xcodec_base.exists()}")

            # Additional debug: check if decoders directory exists
            decoders_dir = xcodec_base / "decoders"
            print(f"πŸ” Decoders directory: {decoders_dir}")
            print(f"πŸ” Decoders directory exists: {decoders_dir.exists()}")

            if decoders_dir.exists():
                all_decoder_files = list(decoders_dir.iterdir())
                print(f"πŸ” All files in decoders directory: {[f.name for f in all_decoder_files]}")
                print(f"πŸ” File sizes: {[(f.name, f.stat().st_size if f.is_file() else 'dir') for f in all_decoder_files]}")

            # Verify critical decoder files (minimum requirement)
            decoder_files = [
                xcodec_base / "decoders" / "decoder_131000.pth",
                xcodec_base / "decoders" / "decoder_151000.pth"
            ]

            missing_decoders = []
            for decoder_file in decoder_files:
                print(f"πŸ” Checking: {decoder_file}")
                exists = decoder_file.exists()
                print(f"πŸ” File exists: {exists}")

                if exists:
                    size = decoder_file.stat().st_size
                    print(f"πŸ” File size: {size} bytes ({size // (1024*1024)} MB)")
                    if size < 1024:
                        missing_decoders.append(decoder_file.name)
                        print(f"⚠️ {decoder_file.name} is too small (likely an LFS pointer)")
                else:
                    missing_decoders.append(decoder_file.name)
                    print(f"⚠️ {decoder_file.name} does not exist")

            if missing_decoders:
                print(f"❌ Critical decoder files missing or incomplete: {missing_decoders}")
                print("Vocoder functionality will not work without decoder files.")
                return False

            print(f"βœ… Successfully downloaded {success_count}/{len(lfs_files)} LFS files")
            print("βœ… All critical decoder files verified present and complete")
            return True

        finally:
            os.chdir(original_cwd)

    except subprocess.CalledProcessError as e:
        print(f"❌ Git clone failed: {e}")
        if e.stdout:
            print(f"stdout: {e.stdout}")
        if e.stderr:
            print(f"stderr: {e.stderr}")
        return False

    except subprocess.TimeoutExpired:
        print("❌ Git clone timed out")
        return False

    except Exception as e:
        print(f"❌ Unexpected error: {e}")
        return False


def ensure_model_availability():
    """

    Ensure all required models are available locally.

    Download them if they don't exist.

    """
    
    xcodec_base = Path("YuE/inference/xcodec_mini_infer")
    
    # Check if critical files exist (both for recons and vocoder stages)
    critical_files = [
        # Vocoder stage files
        xcodec_base / "decoders" / "decoder_131000.pth",
        xcodec_base / "decoders" / "decoder_151000.pth",
        xcodec_base / "decoders" / "config.yaml",

        # Recons stage files (critical for audio decoding)
        xcodec_base / "final_ckpt" / "ckpt_00360000.pth",
        xcodec_base / "final_ckpt" / "config.yaml",

        # Python modules
        xcodec_base / "models" / "soundstream_hubert_new.py"
    ]
    
    missing_files = [f for f in critical_files if not f.exists()]
    
    if missing_files:
        print(f"⚠️ Missing critical model files: {[f.name for f in missing_files]}")
        print("πŸš€ Starting model download with git clone...")

        success = download_xcodec_models()

        if success:
            print("βœ… Model download completed successfully!")
        else:
            print("❌ Model download failed. Vocoder functionality will not work.")
            return False
    else:
        print("βœ… All critical model files are already present")
    
    return True


if __name__ == "__main__":
    """

    Run model download when script is executed directly

    """
    print("🎡 MiloMusic Model Download Script")
    print("=" * 50)
    
    success = ensure_model_availability()
    
    if success:
        print("\nπŸŽ‰ Setup complete! MiloMusic is ready to generate music.")
    else:
        print("\n⚠️ Setup completed with warnings. Check the logs above.")
        exit(1)