Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
chenpangpang
ComfyUI
Commits
4650e7d6
"...targets/git@developer.sourcefind.cn:gaoqiong/migraphx.git" did not exist on "ba07b221460227e15dd29c3b64f1955652917ba4"
Commit
4650e7d6
authored
Jun 27, 2024
by
comfyanonymous
Browse files
Save and load workflow from the flac files output by SaveAudio.
parent
3b423afc
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
164 additions
and
4 deletions
+164
-4
comfy_extras/nodes_audio.py
comfy_extras/nodes_audio.py
+77
-2
web/scripts/app.js
web/scripts/app.js
+14
-1
web/scripts/pnginfo.js
web/scripts/pnginfo.js
+72
-0
web/scripts/ui.js
web/scripts/ui.js
+1
-1
No files found.
comfy_extras/nodes_audio.py
View file @
4650e7d6
...
@@ -3,6 +3,10 @@ import torch
...
@@ -3,6 +3,10 @@ import torch
import
comfy.model_management
import
comfy.model_management
import
folder_paths
import
folder_paths
import
os
import
os
import
io
import
json
import
struct
from
comfy.cli_args
import
args
class
EmptyLatentAudio
:
class
EmptyLatentAudio
:
def
__init__
(
self
):
def
__init__
(
self
):
...
@@ -53,6 +57,61 @@ class VAEDecodeAudio:
...
@@ -53,6 +57,61 @@ class VAEDecodeAudio:
audio
=
vae
.
decode
(
samples
[
"samples"
]).
movedim
(
-
1
,
1
)
audio
=
vae
.
decode
(
samples
[
"samples"
]).
movedim
(
-
1
,
1
)
return
({
"waveform"
:
audio
,
"sample_rate"
:
44100
},
)
return
({
"waveform"
:
audio
,
"sample_rate"
:
44100
},
)
def
create_vorbis_comment_block
(
comment_dict
,
last_block
):
vendor_string
=
b
'ComfyUI'
vendor_length
=
len
(
vendor_string
)
comments
=
[]
for
key
,
value
in
comment_dict
.
items
():
comment
=
f
"
{
key
}
=
{
value
}
"
.
encode
(
'utf-8'
)
comments
.
append
(
struct
.
pack
(
'<I'
,
len
(
comment
))
+
comment
)
user_comment_list_length
=
len
(
comments
)
user_comments
=
b
''
.
join
(
comments
)
comment_data
=
struct
.
pack
(
'<I'
,
vendor_length
)
+
vendor_string
+
struct
.
pack
(
'<I'
,
user_comment_list_length
)
+
user_comments
if
last_block
:
id
=
b
'
\x84
'
else
:
id
=
b
'
\x04
'
comment_block
=
id
+
struct
.
pack
(
'>I'
,
len
(
comment_data
))[
1
:]
+
comment_data
return
comment_block
def
insert_or_replace_vorbis_comment
(
flac_io
,
comment_dict
):
if
len
(
comment_dict
)
==
0
:
return
flac_io
flac_io
.
seek
(
4
)
blocks
=
[]
last_block
=
False
while
not
last_block
:
header
=
flac_io
.
read
(
4
)
last_block
=
(
header
[
0
]
&
0x80
)
!=
0
block_type
=
header
[
0
]
&
0x7F
block_length
=
struct
.
unpack
(
'>I'
,
b
'
\x00
'
+
header
[
1
:])[
0
]
block_data
=
flac_io
.
read
(
block_length
)
if
block_type
==
4
or
block_type
==
1
:
pass
else
:
header
=
bytes
([(
header
[
0
]
&
(
~
0x80
))])
+
header
[
1
:]
blocks
.
append
(
header
+
block_data
)
blocks
.
append
(
create_vorbis_comment_block
(
comment_dict
,
last_block
=
True
))
new_flac_io
=
io
.
BytesIO
()
new_flac_io
.
write
(
b
'fLaC'
)
for
block
in
blocks
:
new_flac_io
.
write
(
block
)
new_flac_io
.
write
(
flac_io
.
read
())
return
new_flac_io
class
SaveAudio
:
class
SaveAudio
:
def
__init__
(
self
):
def
__init__
(
self
):
self
.
output_dir
=
folder_paths
.
get_output_directory
()
self
.
output_dir
=
folder_paths
.
get_output_directory
()
...
@@ -78,11 +137,27 @@ class SaveAudio:
...
@@ -78,11 +137,27 @@ class SaveAudio:
filename_prefix
+=
self
.
prefix_append
filename_prefix
+=
self
.
prefix_append
full_output_folder
,
filename
,
counter
,
subfolder
,
filename_prefix
=
folder_paths
.
get_save_image_path
(
filename_prefix
,
self
.
output_dir
)
full_output_folder
,
filename
,
counter
,
subfolder
,
filename_prefix
=
folder_paths
.
get_save_image_path
(
filename_prefix
,
self
.
output_dir
)
results
=
list
()
results
=
list
()
metadata
=
{}
if
not
args
.
disable_metadata
:
if
prompt
is
not
None
:
metadata
[
"prompt"
]
=
json
.
dumps
(
prompt
)
if
extra_pnginfo
is
not
None
:
for
x
in
extra_pnginfo
:
metadata
[
x
]
=
json
.
dumps
(
extra_pnginfo
[
x
])
for
(
batch_number
,
waveform
)
in
enumerate
(
audio
[
"waveform"
]):
for
(
batch_number
,
waveform
)
in
enumerate
(
audio
[
"waveform"
]):
#TODO: metadata
filename_with_batch_num
=
filename
.
replace
(
"%batch_num%"
,
str
(
batch_number
))
filename_with_batch_num
=
filename
.
replace
(
"%batch_num%"
,
str
(
batch_number
))
file
=
f
"
{
filename_with_batch_num
}
_
{
counter
:
05
}
_.flac"
file
=
f
"
{
filename_with_batch_num
}
_
{
counter
:
05
}
_.flac"
torchaudio
.
save
(
os
.
path
.
join
(
full_output_folder
,
file
),
waveform
,
audio
[
"sample_rate"
],
format
=
"FLAC"
)
buff
=
io
.
BytesIO
()
torchaudio
.
save
(
buff
,
waveform
,
audio
[
"sample_rate"
],
format
=
"FLAC"
)
buff
=
insert_or_replace_vorbis_comment
(
buff
,
metadata
)
with
open
(
os
.
path
.
join
(
full_output_folder
,
file
),
'wb'
)
as
f
:
f
.
write
(
buff
.
getbuffer
())
results
.
append
({
results
.
append
({
"filename"
:
file
,
"filename"
:
file
,
"subfolder"
:
subfolder
,
"subfolder"
:
subfolder
,
...
...
web/scripts/app.js
View file @
4650e7d6
...
@@ -3,7 +3,7 @@ import { ComfyWidgets, initWidgets } from "./widgets.js";
...
@@ -3,7 +3,7 @@ import { ComfyWidgets, initWidgets } from "./widgets.js";
import
{
ComfyUI
,
$el
}
from
"
./ui.js
"
;
import
{
ComfyUI
,
$el
}
from
"
./ui.js
"
;
import
{
api
}
from
"
./api.js
"
;
import
{
api
}
from
"
./api.js
"
;
import
{
defaultGraph
}
from
"
./defaultGraph.js
"
;
import
{
defaultGraph
}
from
"
./defaultGraph.js
"
;
import
{
getPngMetadata
,
getWebpMetadata
,
importA1111
,
getLatentMetadata
}
from
"
./pnginfo.js
"
;
import
{
getPngMetadata
,
getWebpMetadata
,
getFlacMetadata
,
importA1111
,
getLatentMetadata
}
from
"
./pnginfo.js
"
;
import
{
addDomClippingSetting
}
from
"
./domWidget.js
"
;
import
{
addDomClippingSetting
}
from
"
./domWidget.js
"
;
import
{
createImageHost
,
calculateImageGrid
}
from
"
./ui/imagePreview.js
"
;
import
{
createImageHost
,
calculateImageGrid
}
from
"
./ui/imagePreview.js
"
;
import
{
ComfyAppMenu
}
from
"
./ui/menu/index.js
"
;
import
{
ComfyAppMenu
}
from
"
./ui/menu/index.js
"
;
...
@@ -2277,6 +2277,19 @@ export class ComfyApp {
...
@@ -2277,6 +2277,19 @@ export class ComfyApp {
const
workflow
=
pngInfo
?.
workflow
||
pngInfo
?.
Workflow
;
const
workflow
=
pngInfo
?.
workflow
||
pngInfo
?.
Workflow
;
const
prompt
=
pngInfo
?.
prompt
||
pngInfo
?.
Prompt
;
const
prompt
=
pngInfo
?.
prompt
||
pngInfo
?.
Prompt
;
if
(
workflow
)
{
this
.
loadGraphData
(
JSON
.
parse
(
workflow
),
true
,
true
,
fileName
);
}
else
if
(
prompt
)
{
this
.
loadApiJson
(
JSON
.
parse
(
prompt
),
fileName
);
}
else
{
this
.
showErrorOnFileLoad
(
file
);
}
}
else
if
(
file
.
type
===
"
audio/flac
"
)
{
const
pngInfo
=
await
getFlacMetadata
(
file
);
// Support loading workflows from that webp custom node.
const
workflow
=
pngInfo
?.
workflow
;
const
prompt
=
pngInfo
?.
prompt
;
if
(
workflow
)
{
if
(
workflow
)
{
this
.
loadGraphData
(
JSON
.
parse
(
workflow
),
true
,
true
,
fileName
);
this
.
loadGraphData
(
JSON
.
parse
(
workflow
),
true
,
true
,
fileName
);
}
else
if
(
prompt
)
{
}
else
if
(
prompt
)
{
...
...
web/scripts/pnginfo.js
View file @
4650e7d6
...
@@ -163,6 +163,78 @@ export function getLatentMetadata(file) {
...
@@ -163,6 +163,78 @@ export function getLatentMetadata(file) {
});
});
}
}
function
getString
(
dataView
,
offset
,
length
)
{
let
string
=
''
;
for
(
let
i
=
0
;
i
<
length
;
i
++
)
{
string
+=
String
.
fromCharCode
(
dataView
.
getUint8
(
offset
+
i
));
}
return
string
;
}
// Function to parse the Vorbis Comment block
function
parseVorbisComment
(
dataView
)
{
let
offset
=
0
;
const
vendorLength
=
dataView
.
getUint32
(
offset
,
true
);
offset
+=
4
;
const
vendorString
=
getString
(
dataView
,
offset
,
vendorLength
);
offset
+=
vendorLength
;
const
userCommentListLength
=
dataView
.
getUint32
(
offset
,
true
);
offset
+=
4
;
const
comments
=
{};
for
(
let
i
=
0
;
i
<
userCommentListLength
;
i
++
)
{
const
commentLength
=
dataView
.
getUint32
(
offset
,
true
);
offset
+=
4
;
const
comment
=
getString
(
dataView
,
offset
,
commentLength
);
offset
+=
commentLength
;
const
[
key
,
value
]
=
comment
.
split
(
'
=
'
);
comments
[
key
]
=
value
;
}
return
comments
;
}
// Function to read a FLAC file and parse Vorbis comments
export
function
getFlacMetadata
(
file
)
{
return
new
Promise
((
r
)
=>
{
const
reader
=
new
FileReader
();
reader
.
onload
=
function
(
event
)
{
const
arrayBuffer
=
event
.
target
.
result
;
const
dataView
=
new
DataView
(
arrayBuffer
);
// Verify the FLAC signature
const
signature
=
String
.
fromCharCode
(...
new
Uint8Array
(
arrayBuffer
,
0
,
4
));
if
(
signature
!==
'
fLaC
'
)
{
console
.
error
(
'
Not a valid FLAC file
'
);
return
;
}
// Parse metadata blocks
let
offset
=
4
;
let
vorbisComment
=
null
;
while
(
offset
<
dataView
.
byteLength
)
{
const
isLastBlock
=
dataView
.
getUint8
(
offset
)
&
0x80
;
const
blockType
=
dataView
.
getUint8
(
offset
)
&
0x7F
;
const
blockSize
=
dataView
.
getUint32
(
offset
,
false
)
&
0xFFFFFF
;
offset
+=
4
;
if
(
blockType
===
4
)
{
// Vorbis Comment block type
vorbisComment
=
parseVorbisComment
(
new
DataView
(
arrayBuffer
,
offset
,
blockSize
));
}
offset
+=
blockSize
;
if
(
isLastBlock
)
break
;
}
r
(
vorbisComment
);
};
reader
.
readAsArrayBuffer
(
file
);
});
}
export
async
function
importA1111
(
graph
,
parameters
)
{
export
async
function
importA1111
(
graph
,
parameters
)
{
const
p
=
parameters
.
lastIndexOf
(
"
\n
Steps:
"
);
const
p
=
parameters
.
lastIndexOf
(
"
\n
Steps:
"
);
if
(
p
>
-
1
)
{
if
(
p
>
-
1
)
{
...
...
web/scripts/ui.js
View file @
4650e7d6
...
@@ -373,7 +373,7 @@ export class ComfyUI {
...
@@ -373,7 +373,7 @@ export class ComfyUI {
const
fileInput
=
$el
(
"
input
"
,
{
const
fileInput
=
$el
(
"
input
"
,
{
id
:
"
comfy-file-input
"
,
id
:
"
comfy-file-input
"
,
type
:
"
file
"
,
type
:
"
file
"
,
accept
:
"
.json,image/png,.latent,.safetensors,image/webp
"
,
accept
:
"
.json,image/png,.latent,.safetensors,image/webp
,audio/flac
"
,
style
:
{
display
:
"
none
"
},
style
:
{
display
:
"
none
"
},
parent
:
document
.
body
,
parent
:
document
.
body
,
onchange
:
()
=>
{
onchange
:
()
=>
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment