Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

增加previewAudio和loadAudio #60

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file modified .gitignore
100644 → 100755
Empty file.
Empty file modified LICENSE
100644 → 100755
Empty file.
Empty file modified README.md
100644 → 100755
Empty file.
8 changes: 5 additions & 3 deletions __init__.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from .nodes import TextNode, CosyVoiceNode, LoadSRT, CosyVoiceDubbingNode
from .nodes import TextNode,CosyVoiceNode,CosyVoiceDubbingNode,LoadSRT,PreviewAudio,LoadAudio

WEB_DIRECTORY = "./web"

NODE_CLASS_MAPPINGS = {
"LoadSRT":LoadSRT,
"TextNode": TextNode,
"CosyVoiceNode": CosyVoiceNode,
"CosyVoiceDubbingNode":CosyVoiceDubbingNode
"CosyVoiceDubbingNode":CosyVoiceDubbingNode,
"LoadSRT":LoadSRT,
"LoadAudio": LoadAudio,
"PreviewAudio": PreviewAudio,
}
Empty file modified cosyvoice/__init__.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/bin/export_jit.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/bin/export_trt.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/bin/inference.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/bin/train.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/cli/__init__.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/cli/cosyvoice.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/cli/frontend.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/cli/model.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/cli/zh_normalization/README.md
100644 → 100755
Empty file.
Empty file modified cosyvoice/cli/zh_normalization/__init__.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/cli/zh_normalization/char_convert.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/cli/zh_normalization/chronology.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/cli/zh_normalization/constants.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/cli/zh_normalization/num.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/cli/zh_normalization/phonecode.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/cli/zh_normalization/quantifier.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/cli/zh_normalization/text_normlization.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/dataset/__init__.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/dataset/dataset.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/dataset/processor.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/flow/decoder.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/flow/flow.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/flow/flow_matching.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/flow/length_regulator.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/hifigan/f0_predictor.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/hifigan/generator.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/llm/llm.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/transformer/__init__.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/transformer/activation.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/transformer/attention.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/transformer/convolution.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/transformer/decoder.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/transformer/decoder_layer.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/transformer/embedding.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/transformer/encoder.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/transformer/encoder_layer.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/transformer/label_smoothing_loss.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/transformer/positionwise_feed_forward.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/transformer/subsampling.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/utils/__init__.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/utils/class_utils.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/utils/common.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/utils/executor.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/utils/file_utils.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/utils/frontend_utils.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/utils/mask.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/utils/scheduler.py
100644 → 100755
Empty file.
Empty file modified cosyvoice/utils/train_utils.py
100644 → 100755
Empty file.
Empty file modified matcha/VERSION
100644 → 100755
Empty file.
Empty file modified matcha/__init__.py
100644 → 100755
Empty file.
Empty file modified matcha/app.py
100644 → 100755
Empty file.
Empty file modified matcha/cli.py
100644 → 100755
Empty file.
Empty file modified matcha/data/__init__.py
100644 → 100755
Empty file.
Empty file modified matcha/data/components/__init__.py
100644 → 100755
Empty file.
Empty file modified matcha/data/text_mel_datamodule.py
100644 → 100755
Empty file.
Empty file modified matcha/hifigan/LICENSE
100644 → 100755
Empty file.
Empty file modified matcha/hifigan/README.md
100644 → 100755
Empty file.
Empty file modified matcha/hifigan/__init__.py
100644 → 100755
Empty file.
Empty file modified matcha/hifigan/config.py
100644 → 100755
Empty file.
Empty file modified matcha/hifigan/denoiser.py
100644 → 100755
Empty file.
Empty file modified matcha/hifigan/env.py
100644 → 100755
Empty file.
Empty file modified matcha/hifigan/meldataset.py
100644 → 100755
Empty file.
Empty file modified matcha/hifigan/models.py
100644 → 100755
Empty file.
Empty file modified matcha/hifigan/xutils.py
100644 → 100755
Empty file.
Empty file modified matcha/models/__init__.py
100644 → 100755
Empty file.
Empty file modified matcha/models/baselightningmodule.py
100644 → 100755
Empty file.
Empty file modified matcha/models/components/__init__.py
100644 → 100755
Empty file.
Empty file modified matcha/models/components/decoder.py
100644 → 100755
Empty file.
Empty file modified matcha/models/components/flow_matching.py
100644 → 100755
Empty file.
Empty file modified matcha/models/components/text_encoder.py
100644 → 100755
Empty file.
Empty file modified matcha/models/components/transformer.py
100644 → 100755
Empty file.
Empty file modified matcha/models/matcha_tts.py
100644 → 100755
Empty file.
Empty file modified matcha/onnx/__init__.py
100644 → 100755
Empty file.
Empty file modified matcha/onnx/export.py
100644 → 100755
Empty file.
Empty file modified matcha/onnx/infer.py
100644 → 100755
Empty file.
Empty file modified matcha/text/__init__.py
100644 → 100755
Empty file.
Empty file modified matcha/text/cleaners.py
100644 → 100755
Empty file.
Empty file modified matcha/text/numbers.py
100644 → 100755
Empty file.
Empty file modified matcha/text/symbols.py
100644 → 100755
Empty file.
Empty file modified matcha/train.py
100644 → 100755
Empty file.
Empty file modified matcha/utils/__init__.py
100644 → 100755
Empty file.
Empty file modified matcha/utils/audio.py
100644 → 100755
Empty file.
Empty file modified matcha/utils/generate_data_statistics.py
100644 → 100755
Empty file.
Empty file modified matcha/utils/get_durations_from_trained_model.py
100644 → 100755
Empty file.
Empty file modified matcha/utils/instantiators.py
100644 → 100755
Empty file.
Empty file modified matcha/utils/logging_utils.py
100644 → 100755
Empty file.
Empty file modified matcha/utils/model.py
100644 → 100755
Empty file.
Empty file modified matcha/utils/monotonic_align/__init__.py
100644 → 100755
Empty file.
Empty file modified matcha/utils/monotonic_align/core.pyx
100644 → 100755
Empty file.
Empty file modified matcha/utils/monotonic_align/setup.py
100644 → 100755
Empty file.
Empty file modified matcha/utils/pylogger.py
100644 → 100755
Empty file.
Empty file modified matcha/utils/rich_utils.py
100644 → 100755
Empty file.
Empty file modified matcha/utils/utils.py
100644 → 100755
Empty file.
47 changes: 45 additions & 2 deletions nodes.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
import numpy as np
import os,sys
import folder_paths

now_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(now_dir)
input_dir = folder_paths.get_input_directory()
output_dir = os.path.join(folder_paths.get_output_directory(),"cosyvoice_dubb")
pretrained_models = os.path.join(now_dir,"pretrained_models")

#pretrained_models = os.path.join(now_dir,"pretrained_models")
pretrained_models = os.path.join(folder_paths.models_dir, "CosyVoice")
from modelscope import snapshot_download

import ffmpeg
Expand Down Expand Up @@ -344,3 +345,45 @@ def INPUT_TYPES(s):
def load_srt(self, srt):
srt_path = folder_paths.get_annotated_filepath(srt)
return (srt_path,)

class LoadAudio:
@classmethod
def INPUT_TYPES(s):
files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f)) and f.split('.')[-1] in ["wav", "mp3","WAV","flac","m4a"]]
return {"required":
{"audio": (sorted(files),)},
}
CATEGORY = "AIFSH_CosyVoice"
RETURN_TYPES = ("AUDIO",)
FUNCTION = "load_audio"
def load_audio(self, audio):
audio_path = folder_paths.get_annotated_filepath(audio)
#读取文件
waveform, sample_rate = torchaudio.load(audio_path)
audio = {"waveform": waveform.unsqueeze(0),"sample_rate":sample_rate}
return (audio,)

class PreviewAudio:
def __init__(self):
self.preview_count = 00000
@classmethod
def INPUT_TYPES(s):
return {"required":
{"audio": ("AUDIO",),}
}
CATEGORY = "AIFSH_CosyVoice"
RETURN_TYPES = ()
OUTPUT_NODE = True
FUNCTION = "preview_audio"
def preview_audio(self, audio):
#保存文件
filename = "audio_out_"+ f"{self.preview_count:05}"+".wav"
self.preview_count += 1
audioname = os.path.join(folder_paths.get_output_directory(),filename)
torchaudio.save(audioname,audio["waveform"].squeeze(0),audio["sample_rate"])
#torchaudio.save(os.path.join(full_output_folder, file), waveform, audio["sample_rate"], format="FLAC")
#
audio_name = os.path.basename(audioname)
tmp_path = os.path.dirname(audioname)
audio_root = os.path.basename(tmp_path)
return {"ui": {"audio":[audio_name,audio_root]}}
Empty file modified requirements.txt
100644 → 100755
Empty file.
155 changes: 155 additions & 0 deletions web/js/previewAudio.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import { app } from "../../../scripts/app.js";
import { api } from '../../../scripts/api.js'

function fitHeight(node) {
node.setSize([node.size[0], node.computeSize([node.size[0], node.size[1]])[1]])
node?.graph?.setDirtyCanvas(true);
}
function chainCallback(object, property, callback) {
if (object == undefined) {
//This should not happen.
console.error("Tried to add callback to non-existant object")
return;
}
if (property in object) {
const callback_orig = object[property]
object[property] = function () {
const r = callback_orig.apply(this, arguments);
callback.apply(this, arguments);
return r
};
} else {
object[property] = callback;
}
}

function addPreviewOptions(nodeType) {
chainCallback(nodeType.prototype, "getExtraMenuOptions", function(_, options) {
// The intended way of appending options is returning a list of extra options,
// but this isn't used in widgetInputs.js and would require
// less generalization of chainCallback
let optNew = []
try {
const previewWidget = this.widgets.find((w) => w.name === "audiopreview");

let url = null
if (previewWidget.audioEl?.hidden == false && previewWidget.audioEl.src) {
//Use full quality audio
//url = api.apiURL('/view?' + new URLSearchParams(previewWidget.value.params));
url = previewWidget.audioEl.src
}
if (url) {
optNew.push(
{
content: "Open preview",
callback: () => {
window.open(url, "_blank")
},
},
{
content: "Save preview",
callback: () => {
const a = document.createElement("a");
a.href = url;
a.setAttribute("download", new URLSearchParams(previewWidget.value.params).get("filename"));
document.body.append(a);
a.click();
requestAnimationFrame(() => a.remove());
},
}
);
}
if(options.length > 0 && options[0] != null && optNew.length > 0) {
optNew.push(null);
}
options.unshift(...optNew);

} catch (error) {
console.log(error);
}

});
}
function previewAudio(node,file,type){
var element = document.createElement("div");
const previewNode = node;
var previewWidget = node.addDOMWidget("audiopreview", "preview", element, {
serialize: false,
hideOnZoom: false,
getValue() {
return element.value;
},
setValue(v) {
element.value = v;
},
});
previewWidget.computeSize = function(width) {
if (this.aspectRatio && !this.parentEl.hidden) {
let height = (previewNode.size[0]-20)/ this.aspectRatio + 10;
if (!(height > 0)) {
height = 0;
}
this.computedHeight = height + 10;
return [width, height];
}
return [width, -4];//no loaded src, widget should not display
}
// element.style['pointer-events'] = "none"
previewWidget.value = {hidden: false, paused: false, params: {}}
previewWidget.parentEl = document.createElement("div");
previewWidget.parentEl.className = "audio_preview";
previewWidget.parentEl.style['width'] = "100%"
element.appendChild(previewWidget.parentEl);
previewWidget.audioEl = document.createElement("audio");
previewWidget.audioEl.controls = true;
previewWidget.audioEl.loop = false;
previewWidget.audioEl.muted = false;
previewWidget.audioEl.style['width'] = "100%"
previewWidget.audioEl.addEventListener("loadedmetadata", () => {

previewWidget.aspectRatio = previewWidget.audioEl.audioWidth / previewWidget.audioEl.audioHeight;
fitHeight(this);
});
previewWidget.audioEl.addEventListener("error", () => {
//TODO: consider a way to properly notify the user why a preview isn't shown.
previewWidget.parentEl.hidden = true;
fitHeight(this);
});

let params = {
"filename": file,
"type": type,
}

previewWidget.parentEl.hidden = previewWidget.value.hidden;
previewWidget.audioEl.autoplay = !previewWidget.value.paused && !previewWidget.value.hidden;
let target_width = 256
if (element.style?.width) {
//overscale to allow scrolling. Endpoint won't return higher than native
target_width = element.style.width.slice(0,-2)*2;
}
if (!params.force_size || params.force_size.includes("?") || params.force_size == "Disabled") {
params.force_size = target_width+"x?"
} else {
let size = params.force_size.split("x")
let ar = parseInt(size[0])/parseInt(size[1])
params.force_size = target_width+"x"+(target_width/ar)
}

previewWidget.audioEl.src = api.apiURL('/view?' + new URLSearchParams(params));

previewWidget.audioEl.hidden = false;
previewWidget.parentEl.appendChild(previewWidget.audioEl)
}

app.registerExtension({
name: "CosyVoice.AudioPreviewer",
async beforeRegisterNodeDef(nodeType, nodeData, app) {
if (nodeData?.name == "PreviewAudio") {
nodeType.prototype.onExecuted = function (data) {
previewAudio(this, data.audio[0], data.audio[1]);
}
addPreviewOptions(nodeType)
}
}
});
Loading