一、目标
python,利用moviepy和pydub将一段视频进行区间切割
二、源码
1 import os 2 from moviepy.video.io.VideoFileClip import VideoFileClip 3 from pydub import AudioSegment 4 5 6 def clip_video(source_file, target_file, start_time, stop_time): 7 """ 8 利用moviepy进行视频剪切 9 :param source_file: 原视频的路径,mp4格式 10 :param target_file: 生成的目标视频路径,mp4格式 11 :param start_time: 剪切的起始时间点(第start_time秒) 12 :param stop_time: 剪切的结束时间点(第stop_time秒) 13 :return: 14 """ 15 validate_file(source_file) 16 source_video = VideoFileClip(source_file) 17 video = source_video.subclip(int(start_time), int(stop_time)) # 执行剪切操作 18 video.write_videofile(target_file) # 输出文件 19 20 21 def clip_audio(source_file, target_file, start_time, stop_time): 22 """ 23 利用pydub进行音频剪切。pydub支持源文件为 mp4格式,因此这里的输入可以与视频剪切源文件一致 24 :param source_file: 原视频的路径,mp4格式 25 :param target_file: 生成的目标视频路径,mp4格式 26 :param start_time: 剪切的起始时间点(第start_time秒) 27 :param stop_time: 剪切的结束时间点(第stop_time秒) 28 :return: 29 """ 30 validate_file(source_file) 31 audio = AudioSegment.from_file(source_file, "mp4") 32 audio = audio[start_time * 1000: stop_time * 1000] 33 audio_format = target_file[target_file.rindex(".") + 1:] 34 audio.export(target_file, format=audio_format) 35 36 37 def combine_video_audio(video_file, audio_file, target_file, delete_tmp=False): 38 """ 39 利用 ffmpeg将视频和音频进行合成 40 :param video_file: 41 :param audio_file: 42 :param target_file: 43 :param delete_tmp: 是否删除剪切过程生成的原视频/音频文件 44 :return: 45 """ 46 validate_file(video_file) 47 validate_file(audio_file) 48 # 注:需要先指定音频再指定视频,否则可能出现无声音的情况 49 command = "ffmpeg -y -i {0} -i {1} -vcodec copy -acodec copy {2}".format(audio_file, video_file, target_file) 50 os.system(command) 51 if delete_tmp: 52 os.remove(video_file) 53 os.remove(audio_file) 54 55 56 def clip_handle(source_file, target_file, start_time, stop_time, tmp_path=None, delete_tmp=False): 57 """ 58 将一个视频文件按指定时间区间进行剪切 59 :param source_file: 原视频文件 60 :param target_file: 目标视频文件 61 :param start_time: 剪切的起始时间点(第start_time秒) 62 :param stop_time: 剪切的结束时间点(第stop_time秒) 63 :param tmp_path: 剪切过程的文件存放位置 64 :param delete_tmp: 是否删除剪切生成的文件 65 :return: 66 """ 67 # 设置临时文件名 68 if tmp_path is None or not os.path.exists(tmp_path): 69 # 如果没有指定临时文件路径,则默认与目标文件的位置相同 70 tmp_path = target_file[: target_file.rindex("/") + 1] 71 target_file_name = target_file[target_file.rindex("/") + 1: target_file.rindex(".")] 72 tmp_video = tmp_path + "v_" + target_file_name + ".mp4" 73 tmp_audio = tmp_path + "a_" + target_file_name + ".mp4" 74 75 # 执行文件剪切及合成 76 clip_video(source_file, tmp_video, start_time, stop_time) 77 clip_audio(source_file, tmp_audio, start_time, stop_time) 78 combine_video_audio(tmp_video, tmp_audio, target_file, delete_tmp) 79 80 81 def validate_file(source_file): 82 if not os.path.exists(source_file): 83 raise FileNotFoundError("没有找到该文件:" + source_file) 84 85 86 def test_example(): 87 """ 88 测试例子 89 :return: 90 """ 91 root_path = \'XXX/videos/\' 92 video_name = "test.mp4" 93 source_file = root_path + video_name 94 start_time = 5 95 stop_time = 6 96 97 # 设置目标文件名 98 target_name = str(start_time) + "_" + str(stop_time) 99 target_file = root_path + "c_" + target_name + ".mp4" 100 # 处理主函数 101 clip_handle(source_file, target_file, start_time, stop_time) 102 103 104 if __name__ == "__main__": 105 test_example()
三、遇到的问题
1. moviepy切割后的视频没有声音
解决方案:通过pydub切割后再合并
2. 直接利用ffmpeg切割后,视频会出现黑屏、时间区间不准确、分辨率低
解决方案:用了各种命令也没有成功,所以放弃。。。
3. 合并时,不支持mp3、 wav等格式
解决方案:统一保存为mp4