最近开发项目涉及到将mp4视频中的音频提取出来,进行分割;提取视频中的视频帧,间隔60s,用于鉴别视频中的内容信息是否合规。
其实两者共同的原理是,将视频(音频)读出来,获取模块提供的参数,主要是频率,乘以我们理想的时间间隔,就得到了我们在循环处理数据时候的除数,在循环的若干特定时刻拦截需要的数据。
这里用的cv2,安装命令:
pip install opencv-python
官网中这样描述
**a.** Packages for standard desktop environments (Windows, macOS, almost any GNU/Linux distribution)
* run `pip install opencv-python` if you need only main modules
* run `pip install opencv-contrib-python` if you need both main and contrib modules (check extra modules listing from [OpenCV documentation](https://docs.opencv.org/master/))
关于提取视频帧还有一种方法,skimage,但是提取的时候出现了内存不足的问题,小编没有深究问题的原因,选择了另一种方案,以下代码可以参考
from moviepy.editor import *
import wave
import numpy as np
import pylab
import skimage
import imageio
import cv2
# imageio.plugins.ffmpeg.download()
# 本文件的功能是将视频中的音频每分钟生成一个文件,保存成音频文件 在testresult文件夹中
# 视频播放每一分钟,获取视频中的一帧,存成图片 在videoframe文件夹中
def get_audio(video_path='test.mp4', audio_path='test.wav'):
"""
提取视频中的音频,存为audio_path
:str video_path: 视频的地址
:str audio_path: 提取的音频地址
:None:
"""
# moviepy.VideoFileClip: 读取视频到内存,返回一个VideoFileClip的对象
video = VideoFileClip(video_path)
# 获取视频的音频部分
audio = video.audio
# 将视频中的音频部分提取出来,写入test.mp3
audio.write_audiofile(audio_path)
CutTimeDef = 60 # 以60s截断文件
new_path = 'test.wav'
def cut_file(audio_path='test.wav'):
"""
把音频以60s为长度切割
:str audio_path: 音频文件的地址
:None:
"""
FileName = audio_path
print("CutFile File Name is ", FileName)
f = wave.open(r"" + FileName, "rb")
params = f.getparams()
print(params)
nchannels, sampwidth, framerate, nframes = params[:4]
# 60s内的采样次数
CutFrameNum = framerate * CutTimeDef
# 读取格式信息
# 一次性返回所有的WAV文件的格式信息,它返回的是一个元组(tuple):声道数, 量化位数(byte 单位), 采
# 样频率, 采样点数, 压缩类型, 压缩类型的描述。wave模块只支持非压缩的数据,因此可以忽略最后两个信息
# nchannels: 声道数
# sampwidth: 量化位数(byte)
# framerate: 采样频率
# nframes: 采样点数
print("CutFrameNum=%d" % (CutFrameNum))
print("nchannels=%d" % (nchannels))
print("sampwidth=%d" % (sampwidth))
print("framerate=%d" % (framerate))
print("nframes=%d" % (nframes))
# readframes读取音频数据,nframes指定需要读取的长度(整个音频的采样点数)(以取样点为单位)
str_data = f.readframes(nframes)
f.close() # 将波形数据转换成数组
# 需要根据声道数和量化单位,将读取的二进制数据转换为一个可以计算的数组
wave_data = np.fromstring(str_data, dtype=np.short)
wave_data.shape = -1, 2
wave_data = wave_data.T
temp_data = wave_data.T
StepNum = CutFrameNum
StepTotalNum = 0
haha = 0
while StepTotalNum < nframes:
print("Stemp=%d" % (haha))
audio_name = ".\\testresult\\" + FileName[-17:-4] + "-" + str(haha + 1) + ".wav"
print(audio_name)
temp_dataTemp = temp_data[StepNum * (haha):StepNum * (haha + 1)]
haha = haha + 1
StepTotalNum = haha * StepNum
temp_dataTemp.shape = 1, -1
temp_dataTemp = temp_dataTemp.astype(np.short) # 打开WAV文档
f = wave.open(audio_name, "wb") #
# 配置声道数、量化位数和取样频率
f.setnchannels(nchannels)
f.setsampwidth(sampwidth)
f.setframerate(framerate)
# 将wav_data转换为二进制数据写入文件
f.writeframes(temp_dataTemp.tostring())
f.close()
def extract_frame(input_path='test.mp4'):
"""
以60s为间隔提取视频帧,并将其作为图片保存
:str input_path:
:None:
"""
vc = cv2.VideoCapture(input_path)
c = 1
if vc.isOpened():
rval, frame = vc.read()
else:
rval = False
time_interval = 60
# 视频采样的间隔是60s,vc.get(5)获得帧频,CV_CAP_PROP_FPS
timeF = vc.get(5) * time_interval
count = 0
while rval:
print(c)
rval, frame = vc.read()
if c%timeF == 0:
cv2.imwrite(".\\videoframe\\" + str(count) + ".jpg", frame)
count += 1
c += 1
cv2.waitKey(1)
vc.release()
if __name__ == '__main__':
# get_audio()
# cut_file()
extract_frame()
网友评论