ffmpeg.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import configparser
  2. import glob
  3. import os
  4. import random
  5. import re
  6. import subprocess
  7. import sys
  8. import time
  9. import urllib.parse
  10. import json
  11. import requests
  12. from datetime import datetime, timedelta
  13. from urllib.parse import urlencode
  14. class FFmpeg():
  15. """
  16. 获取单个视频时长
  17. """
  18. @classmethod
  19. def get_video_duration(cls, video_url):
  20. ffprobe_cmd = [
  21. "ffprobe",
  22. "-i", video_url,
  23. "-show_entries", "format=duration",
  24. "-v", "quiet",
  25. "-of", "csv=p=0"
  26. ]
  27. output = subprocess.check_output(ffprobe_cmd).decode("utf-8").strip()
  28. return float(output)
  29. """
  30. 获取视频文件的时长(秒)
  31. """
  32. @classmethod
  33. def get_videos_duration(cls, video_file):
  34. result = subprocess.run(
  35. ["ffprobe", "-v", "error", "-show_entries", "format=duration",
  36. "-of", "default=noprint_wrappers=1:nokey=1", video_file],
  37. capture_output=True, text=True)
  38. return float(result.stdout)
  39. """
  40. 视频裁剪
  41. """
  42. @classmethod
  43. def video_tailor(cls, video_url):
  44. output_video_path = ''
  45. # 获取视频的原始宽高信息
  46. ffprobe_cmd = f"ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 {video_url}"
  47. ffprobe_process = subprocess.Popen(ffprobe_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
  48. output, _ = ffprobe_process.communicate()
  49. width, height = map(int, output.decode().strip().split(','))
  50. # 计算裁剪后的高度
  51. new_height = int(height * 0.7)
  52. # 构建 FFmpeg 命令,裁剪视频高度为原始高度的70%,并将宽度缩放为320x480
  53. ffmpeg_cmd = [
  54. "ffmpeg",
  55. "-i", video_url,
  56. "-vf", f"crop={width}:{new_height},scale=320:480",
  57. "-c:v", "libx264",
  58. "-c:a", "aac",
  59. "-y",
  60. output_video_path
  61. ]
  62. # 执行 FFmpeg 命令
  63. subprocess.run(ffmpeg_cmd)
  64. return output_video_path
  65. """
  66. 截取原视频最后一帧
  67. """
  68. @classmethod
  69. def video_png(cls,video_url):
  70. """
  71. png 生成图片位置
  72. :param video_url: 视频地址
  73. :return:
  74. """
  75. png = ''
  76. # 获取视频时长
  77. total_duration = cls.get_video_duration(video_url)
  78. time_offset = total_duration - 1 # 提取倒数第一秒的帧
  79. # 获取视频最后一秒,生成.jpg
  80. subprocess.run(
  81. ['ffmpeg', '-ss', str(time_offset), '-i', video_url, '-t', str(total_duration), '-vf', 'fps=1', png])
  82. return png
  83. """
  84. 生成片尾视频
  85. """
  86. @classmethod
  87. def new_pw_video(cls):
  88. # 添加音频到图片
  89. """
  90. png_path 图片地址
  91. pw_video 提供的片尾视频
  92. pw_duration 提供的片尾视频时长
  93. background_cmd 视频位置
  94. subtitle_cmd 字幕
  95. pw_path 生成视频地址
  96. :return:
  97. """
  98. ffmpeg_cmd = ['ffmpeg', '-loop', '1', '-i', png_path, '-i', pw_video, '-c:v', 'libx264', '-t',
  99. str(pw_duration), '-pix_fmt', 'yuv420p', '-c:a', 'aac', '-strict', 'experimental', '-shortest',
  100. '-vf', f"scale=320x480,{background_cmd},{subtitle_cmd}", pw_path]
  101. subprocess.run(ffmpeg_cmd)
  102. return pw_path