Search code examples
pythonvideoffmpegmp4wav

Combining mp4 with wav in python


I am trying to combine a .mp4 file with a .wav file. I am rendering my mp4 with cv2 videowriter, and I don't think it has anyway of incorporating audio with it. I have tried moviepy.editor, and ffmpeg. moviepy.editor kept messing up the video file and ffmpeg repeatedly kept giving me an error that it couldn't edit existing files in-place. Combining .mp4 with another audio file type is also fine, but if so it would be nice to also answer how to convert midi files to the file type you answered with. Thanks for the help!

moviepy.editor workflow:

video = mpe.VideoFileClip(mp4_path)
os.system(f"timidity {midi_path} -Ow -o {wav_path)}")  # Convert .mid to .wav
video = video.set_audio(mpe.AudioFileClip(wav_path))
video.write_videofile(mp4_path, fps=fps)

ffmpeg workflow:

video = ffmpeg.input(mp4_path)
os.system(f"timidity {midi_path} -Ow -o {wav_path)}")  # Convert .mid to .wav
audio = ffmpeg.input(wav_path)
video = ffmpeg.output(video, audio, path, vcodec='copy', acodec='aac', strict='experimental')
ffmpeg.run(video)

Solution

  • I tested both modules and for moviepy I get correct output video with audio even if I use the same name as output. So I don't know what can mess with output.

    For ffmpeg I had to use different name for output file to resolve problem with couldn't edit existing files in-place

    I had to also use object.video and object.audio to replace audio in output file.

    video  = ffmpeg.input(video_path).video  # get only video channel
    audio  = ffmpeg.input(audio_path).audio  # get only audio channel
    

    My testing code

    def test_moviepy(video_path, audio_path, output_path='output-moviepy.mp4', fps=24):
        import moviepy.editor as mpe
        
        print('--- moviepy ---')
    
        video = mpe.VideoFileClip(video_path)
        video = video.set_audio(mpe.AudioFileClip(audio_path))
        video.write_videofile(output_path, fps=fps)
    
    
    def test_ffmpeg(video_path, audio_path, output_path='output-ffmpeg.mp4', fps=24):
        import ffmpeg
    
        print('--- ffmpeg ---')
    
        video  = ffmpeg.input(video_path).video # get only video channel
        audio  = ffmpeg.input(audio_path).audio # get only audio channel
        output = ffmpeg.output(video, audio, output_path, vcodec='copy', acodec='aac', strict='experimental')
        ffmpeg.run(output)
    
    # --- main ---
    
    video_path  = 'movie.mp4'
    audio_path  = 'sound.wav'
    output_path = 'output.mp4'
    
    test_moviepy(video_path, audio_path)#, output_path)
    test_ffmpeg(video_path, audio_path)#, output_path)
    

    EDIT:

    After installing python module graphviz and program graphviz I could run

    ffmpeg.view(output, filename='output-ffmpeg.png')
    

    to get image

    enter image description here