1. 安装ffmpeg
注意:linux和windows都要在本地安装ffmpeg二进制程序,并且路径要放到Path里
linux安装命令如下:
- sudo add-apt-repository ppa:kirillshkrogalev/ffmpeg-next
- sudo apt-get update
- sudo apt-get install ffmpeg
windows可从下面下载
ffmpeg.zip |
2. 安装ffmpy
- pip install ffmpy
3.ffmpy的简单使用
查看ffmpy文档
其实就是将ffmpeg命令直接放入到ffmpy中, 并在命令行中执行代码
###5. python 使用ffmpy 结合ffmpegimport os import re import logging from django.conf import settings from django.core.cache import cache from ffmpy import FFmpeg from course.constant import VIDEOSTATE logger = logging.getLogger(__name__) def cut_change(video_path, out_path, out_path2, out_path3, base_path, fps_r): """ 操作ffmpeg执行 :param video_path: 处理输入流视频 :param out_path: 合成缩略图 10×10 :param out_path2: 封面图路径 :param out_path3: 合成Ts流和 *.m3u8文件 :param fps_r: 对视频帧截取速度 """ ff = FFmpeg(inputs={video_path: None}, outputs={out_path: '-f image2 -vf fpsfps=fps={},scale=180*75,tile=10x10'.format(fps_r), out_path2: '-y -f mjpeg -ss 0 -t 0.001', None: '-c copy -map 0 -y -f segment -segment_list {0} -segment_time 1 -bsf:v h264_mp4toannexb {1}/cat_output%03d.ts'.format( out_path3, base_path), }) print(ff.cmd) ff.run() def execCmd(cmd): """ 执行计算命令时间 """ r = os.popen(cmd) text = r.read().strip() r.close() return text # 获取完整的上传文件路径 def has_video(video_path): MEDIA_DIR = settings.MEDIA_ROOT FULL_PATH = os.path.join(MEDIA_DIR, video_path) flag = False if os.path.exists(FULL_PATH): flag = True return flag, FULL_PATH, MEDIA_DIR def handle_video_cut(instance): video_path = instance.video.name video_name = os.path.splitext(video_path.split('/')[-1])[0][:5] flag, full_path, media_path = has_video(video_path) base_preview_path = os.path.join(media_path, 'video_trans/preview') base_poster_path = os.path.join(media_path, 'video_trans/poster') base_path = os.path.join(media_path, 'video_trans/video_change', str(instance.id)) # 必须先创建路径, ffmpeg不会自己创建 if not os.path.exists(base_path): os.makedirs(base_path) if not os.path.exists(base_poster_path): os.makedirs(base_poster_path) if not os.path.exists(base_preview_path): os.makedirs(base_preview_path) preview_path = os.path.join(base_preview_path, video_name + '{}_out.png'.format(str(instance.id))) poster_path = os.path.join(base_poster_path, video_name + '{}_poster.jpeg'.format(str(instance.id))) video_change = os.path.join(base_path, 'playlist.m3u8') if not flag: logger.info('this video_path({}) is not exists'.format(full_path)) return None cmd = "ffmpeg -i {} 2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,//".format(full_path) text = execCmd(cmd) search_group = re.search('(\d+):(\d+):(\d+)', text) if search_group: time_hours = int(search_group.group(1)) time_minutes = int(search_group.group(2)) time_seconds = int(search_group.group(3)) all_count_seconds = time_hours * 60 * 60 + time_minutes * 60 + time_seconds # print(all_count_seconds) else: logger.info('this video({}) is no time'.format(full_path)) return None # 因无法精确分配100分压缩图片,存在误差, 以下函数会有错误但是并不会影响结果, 会有exception try: cut_change(full_path, preview_path, poster_path, video_change, base_path, r) except: pass # print('change video code success') logger.info('change video code success and clean cache') return None
5.编码格式的转换
有的mp4格式编码不同, ts流切出来的视频卡顿无法播放, 需要将mp4视频的编码格式转换成 H264, 因为ffmpeg有对应的编码解析器h264_mp4toannexb,其它的编码格式例如:MPEG1, MPEG2, MPEG4等等,目前没有发现ffmpeg相对应的编码解析器,所以建议把.mp4的视频转换成h264的编解码器
- # 比如一个视频的编码是MPEG4,想用H264编码,咋办?
- ffmpeg -i input.mp4 -strict -2 -vcodec h264 output.mp4
- #input.mp4是指要转换视频的地址;output.mp4是转化后视频的存放路径
- # 相反也一样
- ffmpeg -i input.mp4 -strict -2 -vcodec mpeg4 output.mp4
转换前
转换后