mirror of
https://github.com/Comfy-Org/ComfyUI.git
synced 2026-08-16 06:26:34 +08:00
Use PyAV's own predicate instead of querying supported codecs
OutputContainer.supported_codecs only keeps codecs for which avformat_query_codec returns 1, while add_stream_from_template rejects only a falsy result. Muxers that implement neither a query_codec callback nor a codec_tag table return AVERROR_PATCHWELCOME, so they accept a stream copy that supported_codecs reports as impossible: an h264 mpegts source saved with format=auto was fully re-encoded and silently rehoused in mp4. Attempt the copy and let PyAV answer instead. All streams are added before the first packet is muxed, so a stream the destination rejects is caught before anything is written. Handling it per stream also means a subtitle track the destination cannot store is dropped on its own rather than diverting the video alongside it into a needless re-encode. Log the whole-file re-encode at warning, since it is lossy and discards the extra audio and subtitle streams the transcode path does not carry.
This commit is contained in:
@@ -100,17 +100,6 @@ def write_output_metadata(container: InputContainer, output, metadata: dict | No
|
||||
output.metadata[key] = value if isinstance(value, str) else json.dumps(value)
|
||||
|
||||
|
||||
def unsupported_remux_codecs(streams, output_container) -> list[str]:
|
||||
supported = output_container.supported_codecs
|
||||
return [
|
||||
stream.codec_context.name
|
||||
for stream in streams
|
||||
if isinstance(stream, (av.VideoStream, av.AudioStream, SubtitleStream))
|
||||
and stream.codec_context is not None
|
||||
and stream.codec_context.name not in supported
|
||||
]
|
||||
|
||||
|
||||
def mp4_output_open_kwargs(path: str | io.BytesIO, format: VideoContainer, codec: VideoCodec) -> dict:
|
||||
if format != VideoContainer.AUTO and format != VideoContainer.MP4:
|
||||
raise ValueError("Only MP4 format is supported for now")
|
||||
@@ -521,15 +510,6 @@ class VideoFromFile(VideoInput):
|
||||
) -> bool:
|
||||
streams = container.streams
|
||||
with av.open(path, **open_kwargs) as output_container:
|
||||
unsupported = unsupported_remux_codecs(streams, output_container)
|
||||
if unsupported:
|
||||
logging.info(
|
||||
"Cannot copy %s into a %s container; re-encoding instead.",
|
||||
", ".join(sorted(set(unsupported))),
|
||||
output_container.format.name,
|
||||
)
|
||||
return False
|
||||
|
||||
# Add metadata before writing any streams
|
||||
write_output_metadata(container, output_container, metadata)
|
||||
|
||||
@@ -540,7 +520,23 @@ class VideoFromFile(VideoInput):
|
||||
if stream.codec_context is None:
|
||||
logging.warning("Skipping %s stream %d with unsupported codec", stream.type, stream.index)
|
||||
continue
|
||||
out_stream = output_container.add_stream_from_template(template=stream, opaque=True)
|
||||
try:
|
||||
out_stream = output_container.add_stream_from_template(template=stream, opaque=True)
|
||||
except ValueError:
|
||||
codec_name = stream.codec_context.name
|
||||
format_name = output_container.format.name
|
||||
if isinstance(stream, SubtitleStream):
|
||||
logging.warning(
|
||||
"Dropping %s subtitle stream %d: the %s container cannot store it.",
|
||||
codec_name, stream.index, format_name,
|
||||
)
|
||||
continue
|
||||
logging.warning(
|
||||
"The %s container cannot store %s, so the whole file is being re-encoded to H.264/AAC. "
|
||||
"Any additional audio or subtitle streams will be dropped.",
|
||||
format_name, codec_name,
|
||||
)
|
||||
return False
|
||||
stream_map[stream] = out_stream
|
||||
|
||||
# Write packets to the new container
|
||||
|
||||
Reference in New Issue
Block a user