Skip to content

Commit 02440b0

Browse files
Set audio codec to AAC when format=mp4
1 parent 865bd39 commit 02440b0

File tree

1 file changed

+27
-28
lines changed

1 file changed

+27
-28
lines changed

manim/scene/scene_file_writer.py

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,21 @@ def to_av_frame_rate(fps):
5757
return av.utils.Fraction(num, denom)
5858

5959

60+
def convert_audio(input_path: Path, output_path: Path, codec_name: str):
61+
with (
62+
av.open(input_path) as input_audio,
63+
av.open(output_path, "w") as output_audio,
64+
):
65+
input_audio_stream = input_audio.streams.audio[0]
66+
output_audio_stream = output_audio.add_stream(codec_name)
67+
for frame in input_audio.decode(input_audio_stream):
68+
for packet in output_audio_stream.encode(frame):
69+
output_audio.mux(packet)
70+
71+
for packet in output_audio_stream.encode():
72+
output_audio.mux(packet)
73+
74+
6075
class SceneFileWriter:
6176
"""
6277
SceneFileWriter is the object that actually writes the animations
@@ -350,19 +365,7 @@ def add_sound(
350365
# we need to pass delete=False to work on Windows
351366
# TODO: figure out a way to cache the wav file generated (benchmark needed)
352367
wav_file_path = NamedTemporaryFile(suffix=".wav", delete=False)
353-
with (
354-
av.open(file_path) as input_container,
355-
av.open(wav_file_path, "w", format="wav") as output_container,
356-
):
357-
for audio_stream in input_container.streams.audio:
358-
output_stream = output_container.add_stream("pcm_s16le")
359-
for frame in input_container.decode(audio_stream):
360-
for packet in output_stream.encode(frame):
361-
output_container.mux(packet)
362-
363-
for packet in output_stream.encode():
364-
output_container.mux(packet)
365-
368+
convert_audio(file_path, wav_file_path, "pcm_s16le")
366369
new_segment = AudioSegment.from_file(wav_file_path.name)
367370
logger.info(f"Automatically converted {file_path} to .wav")
368371
wav_file_path.close()
@@ -748,21 +751,17 @@ def combine_to_movie(self):
748751
# but tries to call ffmpeg via its CLI -- which we want
749752
# to avoid. This is why we need to do the conversion
750753
# manually.
751-
if config.format == "webm":
752-
with (
753-
av.open(sound_file_path) as wav_audio,
754-
av.open(sound_file_path.with_suffix(".ogg"), "w") as opus_audio,
755-
):
756-
wav_audio_stream = wav_audio.streams.audio[0]
757-
opus_audio_stream = opus_audio.add_stream("libvorbis")
758-
for frame in wav_audio.decode(wav_audio_stream):
759-
for packet in opus_audio_stream.encode(frame):
760-
opus_audio.mux(packet)
761-
762-
for packet in opus_audio_stream.encode():
763-
opus_audio.mux(packet)
764-
765-
sound_file_path = sound_file_path.with_suffix(".ogg")
754+
out_suffix = movie_file_path.suffix.lower()
755+
if config.format == "webm" or out_suffix == ".webm":
756+
ogg_sound_file_path = sound_file_path.with_suffix(".ogg")
757+
convert_audio(sound_file_path, ogg_sound_file_path, "libvorbis")
758+
sound_file_path = ogg_sound_file_path
759+
elif config.format == "mp4" or out_suffix == ".mp4":
760+
# Similarly, pyav may reject wav audio in an .mp4 file;
761+
# convert to AAC.
762+
aac_sound_file_path = sound_file_path.with_suffix(".aac")
763+
convert_audio(sound_file_path, aac_sound_file_path, "aac")
764+
sound_file_path = aac_sound_file_path
766765

767766
temp_file_path = movie_file_path.with_name(
768767
f"{movie_file_path.stem}_temp{movie_file_path.suffix}"

0 commit comments

Comments
 (0)