Skip to content

Instantly share code, notes, and snippets.

@tandy-1000
Last active January 22, 2022 16:41
Show Gist options
  • Save tandy-1000/1a9550249b0929979d37e9ecc680c4b3 to your computer and use it in GitHub Desktop.
Save tandy-1000/1a9550249b0929979d37e9ecc680c4b3 to your computer and use it in GitHub Desktop.
demucser.nim
import std/[os, osproc, logging, algorithm]
const
LOGFILE = "demucser.log"
FFMPEG_CMD = "/usr/bin/ffmpeg"
SOX_CMD = "/usr/bin/sox"
SEGMENT_TIME = 5
SEGMENT_FOLDER = "segments"
DEMUCS = "/usr/bin/python3.9"
DEMUCS_FOLDER = "separated"
DEMUCS_MODEL = "mdx_q"
DEMUCS_FILES = SEGMENT_FOLDER & "/" & DEMUCS_FOLDER & "/" & DEMUCS_MODEL
var fileLog = newFileLogger(LOGFILE)
proc segmentFile(path: string, outFolder: string = SEGMENT_FOLDER, ffmpegCmd: string = FFMPEG_CMD, segmentTime: int = SEGMENT_TIME) =
discard os.existsOrCreateDir(outFolder)
let
outFile = outFolder & '/' & "out%05d" & os.splitFile(path).ext
args = ["-i", path, "-f", "segment", "-segment_time", $segmentTime, "-c", "copy", outFile]
output = osproc.execProcess(ffmpegCmd, args = args, options = {poStdErrToStdOut})
fileLog.log(lvlInfo, output)
proc demucsFile(file: string, demucsCmd: string = DEMUCS, demucsModel: string = DEMUCS_MODEL) =
let
args = ["-m", "demucs", "-d", "cpu", "-n", demucsModel, file]
output = osproc.execProcess(demucsCmd, args = args, options = {poStdErrToStdOut})
fileLog.log(lvlInfo, output)
proc demucsSegments(folder: string = SEGMENT_FOLDER) =
os.setCurrentDir folder
for file in os.walkFiles("*"):
echo file
demucsFile file
os.setCurrentDir os.getAppDir()
proc getSourceSegments(source: string, folder: string = DEMUCS_FILES): seq[string] =
var files: seq[string]
for subFolder in os.walkDir(folder):
for file in os.walkDir(subFolder.path):
let
path = file.path
split = os.splitFile path
if split.name == source:
files.add path
result = sorted(files)
proc concatSegments(soxCmd: string = SOX_CMD) =
let sources = ["bass", "drums", "other", "vocals"]
for source in sources:
let
segments = getSourceSegments(source)
fileName = source & ".wav"
args = segments & @[fileName]
output = osproc.execProcess(soxCmd, args = args, options = {poStdErrToStdOut})
fileLog.log(lvlInfo, output)
when isMainModule:
let path = "~/Downloads/Nobue's Sea/08 Ai No Shizuku.flac"
segmentFile(path)
demucsSegments()
concatSegments()
@tandy-1000
Copy link
Author

A script that uses ffmpeg and sox to run demucs in chunks. Allows machines with less RAM to run demucs on full songs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment