6

I have been using Moviepy to combine several shorter video files into hour long files. Some small files are "broken", they contain video but was not completed correctly (i.e. they play with VLC but there is no duration and you cannot skip around in the video).

I noticed this issue when I try to create a clip using VideoFileClip(file) function. The error that comes up is:

MoviePy error: failed to read the duration of file

Is there a way to still read the "good" frames from this video file and then add them to the longer video?

UPDATE

To clarify, my issue specifically is with the following function call:

clip = mp.VideoFileClip("/home/test/"+file)

Stepping through the code it seems to be an issue when checking the duration of the file in ffmpeg_reader.py where it looks for the duration parameter in the video file. However, since the file never finished recording properly this information is missing. I'm not very familiar with the way video files are structured so I am unsure of how to proceed from here.

Sebo
  • 177
  • 2
  • 4
  • I have updated the question above. My issue is I don't really know how to proceed since I don't know what the duration of the video file is and it could be anywhere from 1 sec to 5 min. To do any sort of video editing using Moviepy a VideoFileClip object has to be made... – Sebo Feb 08 '17 at 19:59
  • Can you provide me with a sample of your video file? If not, I can try to answer as directed above. – mbeacom Apr 13 '17 at 11:26

6 Answers6

0

You're correct. This issue arises commonly when the video duration info is missing from the file. Here's a thread on the issue: GitHub moviepy issue 116

One user proposed the solution of using MP4Box to convert the video using this guide: RASPIVID tutorial

The final solution that worked for me involved specifying the path to ImageMagick's binary file as WDBell mentioned in this post.

I had the path correctly set in my environment variables, but it wasn't till I specificaly defined it in config_defaults.py that it started working: Solution from GitHub discussion

Mikey
  • 107
  • 2
  • 8
  • 2
    A link to a solution is welcome, but please ensure your answer is useful without it: [add context around the link](//meta.stackexchange.com/a/8259) so your fellow users will have some idea what it is and why it’s there, then quote the most relevant part of the page you're linking to in case the target page is unavailable. [Answers that are little more than a link may be deleted.](//stackoverflow.com/help/deleted-answers) – LW001 Feb 24 '18 at 21:46
0

I solved it in a simpler way, with the help of VLC I converted the file to the forma MPEG4 xxx TV/device, and you can now use your new file with python without any problem

xxx = 720p or xxx = 1080p

everything depends on your choice on the output format

I already answered this question on the blog: https://github.com/Zulko/moviepy/issues/116

0

This issue appears when VideoFileClip(file) function from moviepy it looks for the duration parameter in the video file and it's missing. To avoid this (in those corrupted files cases) you should make sure that the total frames parameter is not null before to shoot the function: clip = mp.VideoFileClip("/home/test/"+file)

So, I handled it in a simpler way using cv2.

The idea:

  1. find out the total frames

  2. if frames is null, then call the writer of cv2 and generate a temporary copy of the video clip.

  3. mix the audio from the original video with the copy.

  4. replace the original video and delete copy.

  5. then call the function clip = mp.VideoFileClip("/home/test/"+file)

Clarification: Since OpenCV VideoWriter does not encode audio, the new copy will not contain audio, so it would be necessary to extract the audio from the original video and then mix it with the copy, before replacing it with the original video.

You must import cv2

import cv2

And then add something like this in your code before the evaluation:

cap = cv2.VideoCapture("/home/test/"+file)
frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
fps = int(cap.get(cv2.CAP_PROP_FPS))
print(f'Checking Video {count} Frames {frames} fps: {fps}')

This will surely return 0 frames but should return at least framerate (fps). Now we can set the evaluation to avoid the error and handle it making a temp video:

if frames == 0:
    print(f'No frames data in video {file}, trying to convert this video..')
    writer = cv2.VideoWriter("/home/test/fixVideo.avi", cv2.VideoWriter_fourcc(*'DIVX'), int(cap.get(cv2.CAP_PROP_FPS)),(int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))))                  
    while True:
      ret, frame = cap.read()
      if ret is True:
        writer.write(frame)
      else:
        cap.release()
        print("Stopping video writer")
        writer.release()
        writer = None
        break

Mix the audio from the original video with the copy. I have created a function for this:

def mix_audio_to_video(pathVideoInput, pathVideoNonAudio, pathVideoOutput):
  videoclip = VideoFileClip(pathVideoInput)
  audioclip = videoclip.audio
  new_audioclip = CompositeAudioClip([audioclip])
  videoclipNew = VideoFileClip(pathVideoNonAudio)
  videoclipNew.audio = new_audioclip
  videoclipNew.write_videofile(pathVideoOutput)

mix_audio_to_video("/home/test/"+file, "/home/test/fixVideo.avi", "/home/test/fixVideo.mp4")

replace the original video and delete copys:

os.replace("/home/test/fixVideo.mp4", "/home/test/"+file)
alex1779
  • 41
  • 4
-1

I had the same problem and I have found the solution. I don't know why but if we enter the path in this method path = r'<path>' instead of ("F:\\path") we get no error.

-1

Just click on the C:\Users\gladi\AppData\Local\Programs\Python\Python311\Lib\site-packages\moviepy\video\io\ffmpeg_reader.py

and delete the the code and add this one Provided by me in GITHUB - https://github.com/dudegladiator/Edited-ffmpeg-for-moviepy

  • 2
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/33619071) – Woody1193 Jan 17 '23 at 23:55
-3

clip1=VideoFileClip('path')

c=clip1.duration

print(c)

  • 1
    Hello, welcome to StackOverflow. Please check the FAQ (http://stackoverflow.com/help) about the way this site works. This site is not a discussion board, this is a place for questions to be asked and answered. If you want to answer to someone else, do it as a comment under his question. Commenting requires 50 reputation, review the FAQ about the reputation system. If what you want to write doesn't answer the question, don't post it as an answer. – Tom Burrows Feb 09 '17 at 12:13
  • This will not work since as above, the issue is within the VideoFileClip function. – Sebo Feb 09 '17 at 21:17
  • this comment is not related to the answer! – masoud p Jun 09 '21 at 11:54