【问题标题】:Moviepy unable to read duration of fileMoviepy 无法读取文件的持续时间
【发布时间】:2017-02-08 19:01:50
【问题描述】:

我一直在使用 Moviepy 将几个较短的视频文件组合成一小时长的文件。一些小文件“损坏”,它们包含视频但未正确完成(即它们可以使用 VLC 播放,但没有持续时间,您不能在视频中跳过)。

当我尝试使用 VideoFileClip(file) 函数创建剪辑时,我注意到了这个问题。出现的错误是:

MoviePy 错误:无法读取文件的持续时间

有没有办法仍然从这个视频文件中读取“好”帧,然后将它们添加到更长的视频中?

更新

为了澄清,我的问题具体在于以下函数调用:

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

在检查 ffmpeg_reader.py 中文件的持续时间时,单步执行代码似乎是一个问题,它在视频文件中查找持续时间参数。但是,由于文件从未正确完成记录,因此缺少此信息。我对视频文件的结构不是很熟悉,所以我不确定如何从这里开始。

【问题讨论】:

  • 我已经更新了上面的问题。我的问题是我真的不知道如何进行,因为我不知道视频文件的持续时间是多少,它可能在 1 秒到 5 分钟之间。要使用 Moviepy 进行任何类型的视频编辑,必须制作一个 VideoFileClip 对象...
  • 您能提供一个您的视频文件样本吗?如果没有,我可以尝试按照上面的指示回答。

标签: python video moviepy


【解决方案1】:

你是对的。当文件中缺少视频时长信息时,通常会出现此问题。 这是一个关于这个问题的线程:GitHub moviepy issue 116

一位用户使用本指南提出了使用 MP4Box 转换视频的解决方案:RASPIVID tutorial

对我有用的最终解决方案涉及指定 ImageMagick 二进制文件的路径,如本文中提到的 WDBell。

我在环境变量中正确设置了路径,但直到我在 config_defaults.py 中明确定义它才开始工作:

【讨论】:

【解决方案2】:

我以更简单的方式解决了它,在 VLC 的帮助下,我将文件转换为格式 MPEG4 xxx 电视/设备, 你现在可以在 python 中使用你的新文件,没有任何问题

xxx = 720p 或 xxx = 1080p

一切都取决于您对输出格式的选择

我已经在博客上回答了这个问题:https://github.com/Zulko/moviepy/issues/116

【讨论】:

    【解决方案3】:

    当moviepy 中的VideoFileClip(file) 函数在视频文件中查找持续时间参数时会出现此问题,但该参数丢失了。为了避免这种情况(在那些文件损坏的情况下),您应该确保在拍摄函数之前总帧参数不为空:clip = mp.VideoFileClip("/home/test/"+file)

    所以,我使用 cv2 以更简单的方式处理它。

    想法:

    1. 找出总帧数

    2. 如果 frames 为 null,则调用 cv2 的编写器并生成视频剪辑的临时副本。

    3. 将原始视频中的音频与副本混合。

    4. 替换原始视频并删除副本。

    5. 然后调用函数clip = mp.VideoFileClip("/home/test/"+file)

    澄清:由于 OpenCV VideoWriter 不编码音频,因此新副本将不包含音频,因此需要从原始视频中提取音频,然后将其与副本混合,然后再将其替换为原始视频。

    你必须导入 cv2

    import cv2
    

    然后在评估之前在您的代码中添加类似这样的内容:

    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}')
    

    这肯定会返回 0 帧,但应该至少返回帧率 (fps)。 现在我们可以设置评估以避免错误并处理它制作临时视频:

    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
    

    将原始视频中的音频与副本混合。我为此创建了一个函数:

    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")
    

    替换原始视频并删除副本:

    os.replace("/home/test/fixVideo.mp4", "/home/test/"+file)
    

    【讨论】:

      【解决方案4】:

      clip1=VideoFileClip('路径')

      c=clip1.duration

      打印(c)

      【讨论】:

      • 您好,欢迎来到 StackOverflow。请查看常见问题解答 (stackoverflow.com/help) 关于本网站的工作方式。这个网站不是一个讨论区,这是一个提问和回答的地方。如果您想回答其他人,请在他的问题下进行评论。评论需要 50 名声望,请查看有关声望系统的常见问题解答。如果您想写的内容不能回答问题,请不要将其发布为答案。
      • 这不起作用,因为如上所述,问题出在 VideoFileClip 函数中。
      • 此评论与答案无关!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-01
      • 2018-01-23
      • 1970-01-01
      • 2022-08-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多