一、目標
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
