利用python提取视频帧,可用于从视频中提取图片写文档

# -*- coding:utf-8 -*-
import os
import cv2
from moviepy.editor import *
import time

import os
from moviepy.editor import *


# todo 视频格式转换
def formatchange(path_in, path_out):
    """
    将mov、avi等视频格式转换为mp4格式
    :param path_in: 输入路径
    :param path_out: 输出路径
    :return: 无返回值
    """

    cmd = 'ffmpeg -i ' + path_in + ' -strict -2 -vcodec h264 ' + path_out
    # 执行cmd命令
    os.system(cmd)


# todo 帧率设置
def setfps(inputvideo, fps):
    """
    设置视频帧数
    :param inputvideo:
    :param fps: 帧数,例如25
    :return:
    """
    path, _ = os.path.splitext(inputvideo)
    a = '帧数设置{}.mp4'.format(fps)
    name = path + a
    cmd = 'ffmpeg -i ' + inputvideo + ' -r ' + str(fps) + ' ' + name
    # 执行cmd命令
    os.system(cmd)


# todo 比特率设置
def setbitrate(inputvideo, bitrate):
    """
    改变视频码率,降低码率也可以实现对视频大小的最优化压缩
    :param inputvideo:
    :param bitrate: 例如600k
    :return:
    """
    path, _ = os.path.splitext(inputvideo)
    a = '设置码率{}.mp4'.format(bitrate)
    name = path + a
    cmd = 'ffmpeg -i ' + inputvideo + ' -b:v ' + str(bitrate) + 'k ' + name
    # 执行cmd命令
    os.system(cmd)


# todo 剪掉片头
def cutbegin(inputvideo, time):
    """
    剪切视频片头
    :param inputvideo: 输入视频目录
    :param time: 片头时长
    :return: 无返回值
    """
    clip1 = VideoFileClip(inputvideo)  # 读取视频对象
    path, _ = os.path.splitext(inputvideo)
    mp3 = path + '.mp3'  # 构造mp3保存路径
    outmp3 = path + 'out.mp3'
    end = clip1.duration  # 视频时间总长
    shenyin = clip1.audio
    outname = path + '-剪切片头.mp4'
    if shenyin != None:
        # 如果源视频有声音
        shenyin.write_audiofile(mp3)  # 提取保存视频音频

        os.system(
            "ffmpeg -i {in_path} -vn -acodec copy -ss {Start_time} -t {Dur_time}  {out_path}".format(in_path=mp3,
                                                                                                     out_path=outmp3,
                                                                                                     Start_time=time,
                                                                                                     Dur_time=end))
        if time <= end:
            clip1 = clip1.cutout(0, time)  # 切除片头
            clip1 = clip1.without_audio()  # 去除音频
            name = path + 'cut.mp4'  # 构造名字
            clip1.write_videofile(name, audio=False)  # 保存没有音频的视频
            clip1.close()

            cmd = 'ffmpeg -i ' + name + ' -i ' + outmp3 + ' -strict -2 -f mp4 ' + outname
            # 执行cmd命令
            os.system(cmd)

            # 删除中间生成的多余文件
            os.remove(mp3)
            os.remove(outmp3)
            os.remove(name)
    else:
        # 如果原视频没有声音
        if time <= end:
            clip1 = clip1.cutout(0, time)  # 切除片头
            clip1.write_videofile(outname, audio=False)  # 保存没有音频的视频
            clip1.close()


# todo 剪掉片尾
def cutend(inputvideo, time):
    """
    剪切视频片尾
    :param inputvideo: 输入视频目录
    :param time: 片尾时间节点
    :return: 无返回值
    """
    clip1 = VideoFileClip(inputvideo)  # 读取视频对象
    path, _ = os.path.splitext(inputvideo)
    mp3 = path + '.mp3'  # 构造mp3保存路径
    outmp3 = path + 'out.mp3'
    end = clip1.duration  # 视频时间总长
    shenyin = clip1.audio
    outname = path + '-剪切片尾.mp4'
    if shenyin != None:
        # 如果源视频有声音
        shenyin.write_audiofile(mp3)  # 提取保存视频音频

        os.system(
            "ffmpeg -i {in_path} -vn -acodec copy -ss {Start_time} -t {Dur_time}  {out_path}".format(in_path=mp3,
                                                                                                     out_path=outmp3,
                                                                                                     Start_time=0,
                                                                                                     Dur_time=time))
        if time <= end:
            clip1 = clip1.cutout(time, end)  # 切除片尾
            clip1 = clip1.without_audio()  # 去除音频
            name = path + 'cut.mp4'  # 构造名字
            clip1.write_videofile(name, audio=False)  # 保存没有音频的视频
            clip1.close()

            cmd = 'ffmpeg -i ' + name + ' -i ' + outmp3 + ' -strict -2 -f mp4 ' + outname
            # 执行cmd命令
            os.system(cmd)

            # 删除中间生成的多余文件
            os.remove(mp3)
            os.remove(outmp3)
            os.remove(name)
    else:
        # 如果原视频没有声音
        if time <= end:
            clip1 = clip1.cutout(0, time)  # 切除片头
            clip1.write_videofile(outname, audio=False)  # 保存没有音频的视频
            clip1.close()


# todo 视频裁剪
def star_subclip_end(inputvideo, startime, endtime):
    """
    剪切自己感兴趣的部分视频片段
    :param inputvideo: 输入视频目录
    :param startime: 剪辑开始时间节点
    :param endtime: 剪辑结束时间节点
    :return: 无返回值
    """
    clip1 = VideoFileClip(inputvideo)  # 读取视频对象
    path, _ = os.path.splitext(inputvideo)
    mp3 = path + '.mp3'  # 构造mp3保存路径
    outmp3 = path + 'out.mp3'
    end = clip1.duration  # 视频时间总长
    shenyin = clip1.audio
    outname = path + '-视频剪辑.mp4'
    if shenyin != None:
        # 如果源视频有声音
        shenyin.write_audiofile(mp3)  # 提取保存视频音频

        os.system(
            "ffmpeg -i {in_path} -vn -acodec copy -ss {Start_time} -t {Dur_time}  {out_path}".format(in_path=mp3,
                                                                                                     out_path=outmp3,
                                                                                                     Start_time=startime,
                                                                                                     Dur_time=endtime))
        if endtime <= end:
            clip1 = clip1.subclip(startime, endtime)  # 视频剪辑
            clip1 = clip1.without_audio()  # 去除音频
            name = path + 'cut.mp4'  # 构造名字
            clip1.write_videofile(name, audio=False)  # 保存没有音频的视频
            clip1.close()

            cmd = 'ffmpeg -i ' + name + ' -i ' + outmp3 + ' -strict -2 -f mp4 ' + outname
            # 执行cmd命令
            os.system(cmd)

            # 删除中间生成的多余文件
            os.remove(mp3)
            os.remove(outmp3)
            os.remove(name)
    else:
        # 如果原视频没有声音
        if endtime <= end:
            clip1 = clip1.subclip(startime, endtime)  # 视频剪辑
            clip1.write_videofile(outname, audio=False)  # 保存没有音频的视频
            clip1.close()


# todo 视频旋转
def rotation(inputvideo, rota):
    """
    将视频旋转rota度
    :param inputvideo:
    :param rota:
    :return:
    """
    video1 = VideoFileClip(inputvideo)
    video1 = video1.rotate(rota)
    path, _ = os.path.splitext(inputvideo)
    a = '视频旋转{}度.mp4'.format(rota)
    name = path + a
    video1.write_videofile(name)


# todo 视频镜像
def mirror(inputvideo, model):
    """
    视频镜像
    :param inputvideo:
    :param model: model为1表示水平镜像,为2表示垂直镜像
    :return:
    """
    video1 = VideoFileClip(inputvideo)
    path, _ = os.path.splitext(inputvideo)
    if model == 1:  # 表示水平镜像
        name = path + '水平镜像.mp4'
        (video1.fx(vfx.mirror_x).write_videofile(name, codec='libx264'))
    elif model == 2:  # 表示垂直镜像
        name = path + '垂直镜像.mp4'
        (video1.fx(vfx.mirror_y).write_videofile(name, codec='libx264'))


# todo 视频缩放
def setsize(inputvideo, w_size, h_size):
    """
    视频按尺寸进行缩放,等比例缩小相当于下调分辨率
    :param inputvideo:
    :param w_size: 视频宽度
    :param h_size: 视频高度
    :return:
    """
    ship = VideoFileClip(inputvideo)
    clip = ship.resize([w_size, h_size])
    path, _ = os.path.splitext(inputvideo)
    a = '视频缩放为{}x{}.mp4'.format(w_size, h_size)
    name = path + a
    clip.write_videofile(name)


# todo 调整视频分辨率
def setresolution(inputvideo, w_size, h_size):
    """
    调整视频分辨率
    :param inputvideo:
    :param w_size: 目标视频宽度
    :param h_size: 目标视频高度
    :return:
    """
    path, _ = os.path.splitext(inputvideo)
    a = '调整分辨率{}x{}.mp4'.format(w_size, h_size)
    name = path + a
    cmd = 'ffmpeg -i ' + inputvideo + ' -s ' + str(w_size) + 'x' + str(h_size) + ' ' + name
    # 执行cmd命令
    os.system(cmd)


# todo 视频压缩
def setbitrate(inputvideo, bitrate):
    """
    改变视频码率,降低码率也可以实现对视频大小的最优化压缩
    :param inputvideo:
    :param bitrate: 例如600k
    :return:
    """
    path, _ = os.path.splitext(inputvideo)
    a = '设置码率{}.mp4'.format(bitrate)
    name = path + a
    cmd = 'ffmpeg -i ' + inputvideo + ' -b:v ' + str(bitrate) + 'k ' + name
    # 执行cmd命令
    os.system(cmd)


# todo 添加文字水印

# todo 添加跑马灯文字水印

# todo 画中画

# todo 添加背景音乐
def addmp3(inputvideo, mp3path):
    """
    给视频增加音频
    :param inputvideo: 输入视频目录
    :param mp3path: 输入音频目录
    :return:
    """
    path, _ = os.path.splitext(inputvideo)
    a = '增加音频{}.mp4'.format(mp3path)
    outname = path + a
    cmd = 'ffmpeg -i ' + inputvideo + ' -i ' + mp3path + ' -strict -2 -f mp4 ' + outname
    os.system(cmd)


# todo 倍速播放
def speedplay(inputvideo, speed):
    """
    倍速播放
    :param inputvideo:
    :param speed: 速度,例如1.5
    :return:
    """

    path, _ = os.path.splitext(inputvideo)
    a = '改变速度{}.mp4'.format(speed)
    outname = path + a
    video = VideoFileClip(inputvideo)
    result = video.fl_time(lambda t: speed * t,
                           apply_to=['mask', 'video', 'audio']).set_end(video.end / speed)
    result.write_videofile(outname)


# todo 添加片头
def addstarvideo(inputvideo, starvideo):
    """
    添加片头
    :param inputvideo:
    :param starvideo:
    :return:
    """
    path, _ = os.path.splitext(inputvideo)
    a = '增加片头{}.mp4'.format(starvideo)
    outname = path + a
    video1 = VideoFileClip(starvideo)
    video2 = VideoFileClip(inputvideo)
    video3 = concatenate_videoclips([video1, video2])
    video3.write_videofile(outname)


# todo 添加片尾
def addendvideo(inputvideo, endvideo):
    """
    添加片尾
    :param inputvideo:
    :param endvideo:
    :return:
    """
    path, _ = os.path.splitext(inputvideo)
    a = '增加片尾{}.mp4'.format(endvideo)
    outname = path + a
    video1 = VideoFileClip(inputvideo)
    video2 = VideoFileClip(endvideo)
    video3 = concatenate_videoclips([video1, video2])
    video3.write_videofile(outname)


# todo 视频分段,具体根视频的裁剪一个道理,加上一个业务逻辑就变成视频分段了

# todo 视频合成
def comvideo(inputvideo, endvideo):
    """
    视频合成
    :param inputvideo:合成的第一段视频
    :param endvideo:合成的第二段视频
    :return:
    """
    path, _ = os.path.splitext(inputvideo)
    a = '视频空间合成{}.mp4'.format(endvideo)
    outname = path + a
    video1 = VideoFileClip(inputvideo)
    video2 = VideoFileClip(endvideo)
    video3 = CompositeVideoClip([video1, video2])
    video3.write_videofile(outname)

# todo 自动生成电影混剪




def clipVideo(video):
    clip = VideoFileClip(video)
    clip = clip.subclip(90, clip.duration)
    cur_dir = os.path.dirname(os.path.abspath(video))
    cur_name=os.path.basename(video)
    file_name = video.split('.')[0]  # 拆分视频文件名称 ,剔除后缀
    new_file =file_name+ str(int(time.time())) + '_subclip.mp4'
    clip.write_videofile(new_file)

def filter_file(filter,dirname):
    result = []  # 所有的文件
    for maindir, subdir, file_name_list in os.walk(dirname):
        for filename in file_name_list:
            apath = os.path.join(maindir, filename)  # 合并成一个完整路径
            ext = os.path.splitext(apath)[1]  # 获取文件后缀 [0]获取的是除了文件名以外的内容
            #print('ext',ext)
            if ext in filter:
                result.append(apath)
    return result
def save_img2(videos):  # 提取视频中图片 按照每秒提取   间隔是视频帧率
    #f_save_path = r'C:/Users/19088/Desktop/pypics/'  # 保存图片的上级目录
    #videos = os.listdir(video_path)  # 返回指定路径下的文件和文件夹列表。
    for video_name in videos:  # 依次读取视频文件
        #print('videoname:{0}'.format(video_name))
        cur_dir = os.path.dirname(os.path.abspath(video_name))
        cur_name=os.path.basename(video_name)
        print("curDir:{0} curname:{1}".format(cur_dir,cur_name))
        file_name = video_name.split('.')[0]  # 拆分视频文件名称 ,剔除后缀
        #folder_name = cur_dir+"/" + file_name  # 保存图片的上级目录+对应每条视频名称 构成新的目录存放每个视频的
        #os.makedirs(folder_name, exist_ok=True)  # 创建存放视频的对应目录
        folder_name=cur_dir
        vc = cv2.VideoCapture(video_name)  # 读入视频文件
        #vc = cv2.VideoCapture(video_path + video_name)  # 读入视频文件
        fps = vc.get(cv2.CAP_PROP_FPS)  # 获取帧率
        print(fps)  # 帧率可能不是整数  需要取整
        rval = vc.isOpened()  # 判断视频是否打开  返回True或False
        #c = 1
        n=1
        fps=0.2     #10000fps 约5分钟
        totalframs=vc.get(cv2.CAP_PROP_FRAME_COUNT)
        while rval and fps<1.0:  # 循环读取视频帧
            vc.set(cv2.CAP_PROP_POS_FRAMES ,fps*totalframs)
            rval, frame = vc.read()  # videoCapture.read() 函数,第一个返回值为是否成功获取视频帧,第二个返回值为返回的视频帧:
            pic_path = folder_name + '/'
            print("rival",rval)
            if rval:
                #if (1 or c % round(fps) == 0):  # 每隔fps帧进行存储操作   ,可自行指定间隔
                    #cv2.imwrite(pic_path + 'video_' + str(round(n)) + '.png', frame) #存储为图像的命名 video_数字(第几个文件).png
                savepath=pic_path + cur_name[-15:-5]+"_" + str(round(n)) + '.jpg'
                cv2.imencode('.jpg',frame)[1].tofile(savepath)
                print(savepath)
                fps+=0.15
                n+=1
                #break
                cv2.waitKey(1)  # waitKey()--这个函数是在一个给定的时间内(单位ms)等待用户按键触发;如果用户没有按下键,则接续等待(循环)
                #c = c + 1
            else:
                break
        vc.release()
        print('save_success' + folder_name)
def main():
    video_path = r'H:/newFolder/GUOCHAN/shtGuochanJP/dist/videoproject/upload/pics/'  # 视频所在的路径
    filelist=filter_file(r'.mp4',video_path)            #获取所有视频
    #cutbegin(filelist[0],90)
    print("files:{0}".format(filelist))
    print("dealing:....")
    save_img2(filelist)
if __name__ == '__main__':
    main()
#save_img2()

import cv2
import os
import hashlib

#视频文件名与对应提取帧数的索引
file_dict = {"2017-07-04-07-39-28_fovs5.h264": (list(range(2030,3150)) + list(range(3960,4050))),
             "2017-07-04-09-41-55_fovs5.h264": (list(range(1100,1700)) + list(range(2430,4450))),
             "2017-07-04-09-50-22_fovs5.h264": (list(range(0,1240)) + list(range(2200,9000)) + list(range(11320,14000)))}

#计算视频文件的md5值
def getFileMD5(filepath):
    f = open(filepath, 'rb')
    md5obj = hashlib.md5()
    md5obj.update(f.read())
    hash = md5obj.hexdigest()
    f.close()
    return str(hash).upper()

#提取视频中对应帧数段的图片
def selct_sample(video_path,target_path,video_index,filemd5,frameFrequency,extract_num):
    
    cap = cv2.VideoCapture(video_path)
    frame_index = 0
    while True:
        res, image = cap.read()
        if not res:
            print('not res, not image')
            break

        if frame_index % frameFrequency == 0 and frame_index in extract_num:
            image_name = ("{}_{}_{}.png".format(
                          (str(video_index)).zfill(4),  #视频的序列索引
                          filemd5,      #视频的md5值
                          (str(frame_index)).zfill(5))  #帧数
                         )
            cv2.imwrite(os.path.join(target_path,image_name),image)
            print("正在截取:{} ---> {}帧".format(os.path.basename(target_path),frame_index))
        frame_index += 1
    print("图片提取结束")
    cap.release()


def gen_sample(video_path,target_path,video_index,filemd5,frameFrequency):

    cap = cv2.VideoCapture(video_path)
    frame_index = 0
    while True:
        res, image = cap.read()
        if not res:
            print('not res, not image')
            break
        if frame_index % frameFrequency == 0:
            image_name = ("{}_{}_{}.png".format(
                          (str(video_index)).zfill(4),  #视频的序列索引
                          filemd5,      #视频的md5值
                          (str(frame_index)).zfill(5))  #帧数
                         )
            cv2.imwrite(os.path.join(target_path,image_name),image)
            print("正在截取:{} ---> {}帧".format(os.path.basename(target_path),frame_index))
        frame_index += 1
    print("图片提取结束")
    cap.release()


def main():
    #需要处理的视频路径; linux和windows下面注意路径的读取方式有所不同
    src_path = r'C:/Users/19088/Desktop/pypics/'
    #目标文件夹路径
    target_path = r'D:/pypics/'
    #设置间隔帧数
    frameFrequency = 100000
    # 获取文件路径
    filelist = os.listdir(src_path)
    video_num = len(filelist)
    print("视频个数为:%d" % video_num)
    for item in filelist:
        #设置视频的索引个数
        video_index = 0
        if item.endswith(('.h264','.mp4','.mkv','avi')):
            video_path = os.path.join(src_path,item)
            #获取视频唯一的md5值
            filemd5 = getFileMD5(video_path)
            filename  = item.split(".")[0]
            outPutDir = os.path.join(target_path,filename)
            if not os.path.exists(outPutDir):
                os.mkdir(outPutDir)
            #截取图片
            gen_sample(video_path,outPutDir,video_index,filemd5,frameFrequency)
#            extract_num = file_dict[item]
#            selct_sample(video_path,outPutDir,video_index,filemd5,frameFrequency,extract_num)
            video_index += 1

if __name__ == '__main__':
    main()

你可能感兴趣的:(python专栏,python,音视频,ffmpeg)