Zulko / moviepy

Video editing with Python
https://zulko.github.io/moviepy/
MIT License
12.42k stars 1.55k forks source link

Inaccurate audio clip duration for MP3 files causing `OSError` #2004

Open RapahelS opened 1 year ago

RapahelS commented 1 year ago

When using moviepy to process certain MP3 audio files, the reported duration of the audio clip is less than the actual duration. This discrepancy leads to an OSError when moviepy tries to access a part of the audio file that exceeds the reported duration.

Steps to reproduce:

  1. Load an MP3 audio file using AudioFileClip from moviepy.editor.
  2. Print the duration of the audio clip using the duration attribute.
  3. Compare the reported duration with the actual duration of the audio file (e.g., using a tool like eyed3 for .mp3 files).

Expected behavior:

The reported duration of the audio clip should match the actual duration of the MP3 audio file.

Actual behavior:

The reported duration of the audio clip is less than the actual duration of the MP3 audio file. This leads to an OSError when moviepy tries to access a part of the audio file that exceeds the reported duration.

Environment:

Additional context:

The issue seems to be related to how the duration of the MP3 audio file is extracted from the file's metadata in the FFMPEG_AudioReader class. The reported duration is used to calculate the number of frames in the file, which can lead to an attempt to access non-existent frames if the reported duration is less than the actual duration.

Error Message: ... AppData\Local\Programs\Python\Python310\lib\site-packages\moviepy\audio\io\readers.py", line 170, in get_frame raise IOError("Error in file %s, "%(self.filename)+ OSError: Error in file D:\Video Editing\music.mp3, Accessing time t=184.04-184.08 seconds, with clip duration=184 seconds,

Example code:

import moviepy.editor as mpy
import os
import random

def add_background_music_to_clip(clip, music_directory):
    """
    Adds background music to a video clip.
    """
    # Select a random music file
    music_files = [f for f in os.listdir(music_directory) if f.endswith('.mp3')]
    music_file = random.choice(music_files)

    # Open the music file
    music = mpy.AudioFileClip(os.path.join(music_directory, music_file))

    # Trim or repeat the music to match the length of the clip and adjust the volume
    music = music.subclip(0, clip.duration).volumex(0.028)

    print(f'Clip duration: {clip.duration}, Background music duration: {music.duration}')  # Print durations

    # Fade out the music
    music = music.audio_fadeout(3)

    # Combine the original audio and the music
    final_audio = mpy.CompositeAudioClip([clip.audio, music])

    # Return the clip with the new background music
    return clip.set_audio(final_audio)

EuroNutellaMan commented 1 year ago

I'm having this same issue on Endeavour OS.

Moviepy version: 1.0.3-4 Python version: 3.11.3 64-bit

I too have a program that tries to add the audio track to a video and apparently the length is different.

ChatGPT suggested I do this:

# Match audio duration to video duration
audio = audio.set_duration(video.duration)

but it doesn't actually fix it and I still get this error: Error: must be real number, not NoneType

Spacepro0 commented 9 months ago

Any updates on this? I am having the same issue.

SohamTilekar commented 9 months ago

In Moviepy any set method is not Working. Full Bug and Way Around #2084

Temp Way Around. audio.duration = video.duration or # Your Duration

cal-overflow commented 9 months ago

I'm having this issue as well. I've used various approaches to changing the duration of an audio clip to fill a longer video clip duration.

Here's everything I've tried and they all result in the same Accessing time t=x.yz seconds, with clip ... error


video_file = VideoFileClip("video.mp4") # video of length 10 seconds
audio_file = AudioFileClip("audio.mp3") # audio of length ~3 seconds
target_duration = video_file.duration

# approach 1
audio = audio_file.set_duration(target_duration)
# approach 2
audio = audio_file.set_end(target_duration)
# approach 3
audio = audio_file.subclip(0, target_duration)

audio.write_audiofile() # Throws the same error regardless of which approach above is used

I've also tried manipulating the audio_file.duration directly but that doesn't work for me either.

Here's a little more about the error.

File "~/path-to-project/venv/lib/python3.11/site-packages/moviepy/audio/io/readers.py", line 170, in get_frame
    raise IOError("Error in file %s, "%(self.filename)+
OSError: Error in file tmp/audio_intro.mp3, Accessing time t=3.53-3.58 seconds, with clip duration=3 seconds

Edit: I worked around this by using the CompositeAudioClip and not worrying about setting the duration of the original audio clip. This doesn't help with the duration issue, though.

video_file = VideoFileClip("video.mp4") # video of length 10 seconds
audio_file = AudioFileClip("audio.mp3") # audio of length ~3 seconds
target_duration = video_file.duration

audio = CompositeAudioClip([ audio_file ])

audio.write_audiofile()
Spacepro0 commented 7 months ago

Any updates on this? I am having the same issue.

I ended up fixing this by using the WAV file format type. I am not sure what caused the issue with MP3 but if it's an option I recommend switching.

SohamTilekar commented 7 months ago

Use py version 3.8 it will be fixed. Or there is problem with the codec which is used.