Skip to content

Commit

Permalink
Updated README
Browse files Browse the repository at this point in the history
  • Loading branch information
adefossez committed Jan 31, 2020
1 parent 3c7876d commit 9c3a561
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 20 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@ Demucs and Conv-Tasnet obtain the same SDR. See [our paper][demucs_arxiv] Sectio
width="800px"></p>


## Important news if you are already using Demucs

- 31/01/2020: **You will need to re-download pre-trained models**. Due to an incompatiblity with Pytorch 1.4.0, the pre-trained models could not be loaded
with it. I have replaced all the pre-trained models using a more future proof serialization. It means
that you will get an error if you update the repo saying that the previously downloaded checkpoints
don't have the right signature. Please delete the previously downloaded files in `models` and it will download the new ones.
Sorry for the inconveniance.
- 31/01/2020: **New light models**: I have added a lighter version of Demucs, trained with the option `--channels=64`.
The overall SDR is a bit worse, but to the hear it sounds quite similar. The files are smaller to download (1GB),
and it should run about 4x faster. I know quite a few people wanted to use Demucs on GPU, I hope this version
can run on a wider range of hardware :) To use it simply replace `-n demucs` by `-n light` (or `-n light_extra`
for the version trained on more data)
in the `separate` command described hereafter.

## Comparison with other models

Expand Down Expand Up @@ -150,6 +163,8 @@ Other pre-trained models can be selected with the `-n` flag and downloaded with
The models will be stored in the `models` folder. The list of pre-trained models is:
- `demucs`: Demucs trained on MusDB,
- `demucs_extra`: Demucs trained with extra training data,
- `light`: Demucs trained on MusDB with `--channels=64` (smaller, faster, quality might be a bit worse),
- `light_extra`: Demucs trained with extra training data with `--channels=64`,
- `tasnet`: Conv-Tasnet trained on MusDB,
- `tasnet_extra`: Conv-Tasnet trained with extra training data.

Expand Down
52 changes: 33 additions & 19 deletions demucs/separate.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,18 @@
from .audio import AudioFile
from .utils import apply_model, load_model

BASE_URL = "https://dl.fbaipublicfiles.com/demucs/"
BASE_URL = "https://dl.fbaipublicfiles.com/demucs/v2.0/"
PRETRAINED_MODELS = {
'demucs': 'b25b32a4772e43983d2e30cce17a85aaa1baf3aea0a6145eb591b0f393ac9312',
'demucs_extra': '099d3e7fcbb8da7484184ad6d84cd6c3820947ff0e2f52d5e622365685037cd7',
'tasnet': 'd037cdbad294f1a7152af8742d8419c305e244810381a795ffcd22b8593360d8',
'tasnet_extra': '4a91ade51439ac41bb1914753c3aebd839eed17981379e6142478bcfa3a5461f',
'demucs': 'f6c4148ba0dc92242d82d7b3f2af55c77bd7cb4ff1a0a3028a523986f36a3cfd',
'demucs_extra': '3331bcc5d09ba1d791c3cf851970242b0bb229ce81dbada557b6d39e8c6a6a87',
'light': '79d1ee3c1541c729c552327756954340a1a46a11ce0009dea77dc583e4b6269c',
'light_extra': '9e9b4af564229c80cc73c95d02d2058235bb054c6874b3cba4d5b26943a5ddcb',
'tasnet': 'be56693f6a5c4854b124f95bb9dd043f3167614898493738ab52e25648bec8a2',
'tasnet_extra': '0ccbece3acd98785a367211c9c35b1eadae8d148b0d37fe5a5494d6d335269b5',
}


def download_file(url, target, sha256=None):
def download_file(url, target):
"""
Download a file with a progress bar.
Expand All @@ -39,21 +41,11 @@ def _download():
response = requests.get(url, stream=True)
total_length = int(response.headers.get('content-length', 0))

if sha256 is not None:
hasher = hashlib.sha256()

with tqdm.tqdm(total=total_length, unit="B", unit_scale=True) as bar:
with tqdm.tqdm(total=total_length, ncols=120, unit="B", unit_scale=True) as bar:
with open(target, "wb") as output:
for data in response.iter_content(chunk_size=4096):
output.write(data)
if sha256 is not None:
hasher.update(data)
bar.update(len(data))
if sha256 is not None:
signature = hasher.hexdigest()
if sha256 != signature:
raise ValueError("Invalid sha256 signature when downloading {}. "
"Expected {} but got {}".format(url, sha256, signature))

try:
_download()
Expand All @@ -63,6 +55,26 @@ def _download():
raise


def verify_file(target, sha256):
hasher = hashlib.sha256()
with open(target, "rb") as f:
while True:
data = f.read(65536)
if not data:
break
hasher.update(data)
signature = hasher.hexdigest()
if signature != sha256:
print(
f"Invalid sha256 signature for the file {target}. Expected {sha256} but got "
f"{signature}.\nIf you have recently updated the repo, it is possible "
"the checkpoints have been updated. It is also possible that a previous "
f"download did not run to completion.\nPlease delete the file '{target.absolute()}' "
"and try again.",
file=sys.stderr)
sys.exit(1)


def main():
parser = argparse.ArgumentParser("demucs.separate",
description="Separate the sources for the given tracks")
Expand Down Expand Up @@ -105,8 +117,8 @@ def main():

args = parser.parse_args()
model_path = args.models / f"{args.name}.th"
sha256 = PRETRAINED_MODELS.get(args.name)
if not model_path.is_file():
sha256 = PRETRAINED_MODELS.get(args.name)
if sha256 is None:
print(f"No pretrained model {args.name}", file=sys.stderr)
sys.exit(1)
Expand All @@ -119,7 +131,9 @@ def main():
args.models.mkdir(exist_ok=True, parents=True)
url = BASE_URL + f"{args.name}.th"
print("Downloading pre-trained model weights, this could take a while...")
download_file(url, model_path, sha256)
download_file(url, model_path)
if sha256 is not None:
verify_file(model_path, sha256)
model = load_model(model_path)
out = args.out / args.name
out.mkdir(parents=True, exist_ok=True)
Expand Down
2 changes: 1 addition & 1 deletion demucs/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def apply_model(model, mix, shifts=None, split=False, progress=False):
offsets = range(0, length, shift)
scale = 10
if progress:
offsets = tqdm.tqdm(offsets, unit_scale=scale, unit='seconds')
offsets = tqdm.tqdm(offsets, unit_scale=scale, ncols=120, unit='seconds')
for offset in offsets:
chunk = mix[..., offset:offset + shift]
chunk_out = apply_model(model, chunk, shifts=shifts)
Expand Down

0 comments on commit 9c3a561

Please sign in to comment.