video_concat.py 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import os
  2. import time
  3. import json
  4. import subprocess
  5. from .logger_config import setup_logger
  6. # 设置日志
  7. logger = setup_logger(__name__)
  8. def get_video_duration(video_path):
  9. """
  10. 获取视频时长(以秒为单位)。
  11. """
  12. command = f'ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "{video_path}"'
  13. result = subprocess.run(command, shell=True, capture_output=True, text=True)
  14. return float(result.stdout.strip())
  15. def merge_video(video_1, video_2, video_output, fade_duration=0.2):
  16. logger.info(f"口播视频拼接。。。")
  17. # 获取 video_1 的时长
  18. video_1_duration = get_video_duration(video_1)
  19. # 设置转场和淡入淡出效果
  20. filter_complex = f"""
  21. [0:v]fade=type=out:duration={fade_duration}:start_time={video_1_duration - fade_duration}[v0f];
  22. [1:v]fade=type=in:duration={fade_duration}:start_time=0[v1f];
  23. [v0f][v1f]concat=n=2:v=1:a=0[outv];
  24. [0:a][1:a]acrossfade=d={0.1}[outa]
  25. """.replace("\n", "")
  26. # 执行视频拼接
  27. command = f'ffmpeg -i {video_1} -i {video_2} -filter_complex "{filter_complex}" -map "[outv]" -map "[outa]" -y {video_output}'
  28. subprocess.run(command, shell=True)
  29. def concat_videos(video_list):
  30. """
  31. 按列表顺序拼接多个视频。
  32. Args:
  33. video_list (list): 视频文件路径列表
  34. """
  35. if len(video_list) < 2:
  36. logger.error("至少需要两个视频进行拼接。")
  37. return
  38. # 使用第一个视频作为初始视频
  39. merged_video = video_list[0]
  40. for idx, video in enumerate(video_list[1:], start=1):
  41. output_file = f'output/oral_video/merged_video_{idx}.mp4'
  42. merge_video(merged_video, video, output_file)
  43. merged_video = output_file
  44. # 最终合并结果重命名为 merged_video.mp4
  45. video_name = os.path.splitext(os.path.basename(video_list[0]))[0].split('_')[0]
  46. final_output = f"output/oral_video/final-{video_name}.mp4"
  47. subprocess.run(f'mv {merged_video} {final_output}', shell=True)
  48. logger.info(f"最终合并视频保存为 {final_output}")
  49. return final_output
  50. if __name__ == "__main__":
  51. input_files = [
  52. "./output/video_clips/test_video_003.mp4",
  53. "./output/video_clips/test_video_002.mp4",
  54. "./output/video_clips/test_video_004.mp4",
  55. ]
  56. merge_videos(input_files)