【新仁填坑031】opencv和ffmpeg和pydub音频处理相关及PermissionError: [Errno 13] Permission denied:‘C:\User\Temp\...

问题描述

使用pydub播放音频时总是显示临时文件写入时权限不够报错

问题图

在这里插入图片描述

安装pyaudio 解决

pip install pyaudio -i https://pypi.douban.com/simple

在这里插入图片描述

播放音频安装过程总结:

需要安装两个库 和 一个工具 之前报错是因为只安装了一个库

安装音频相关库

pip install pydub -i https://pypi.douban.com/simple
pip install pyaudio -i https://pypi.douban.com/simple
(pyaudio 如果安装报错什么c++ 可以先把这个文件下载下来然后本地安装)
通用下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml
ctrl+f 搜索pyaudio 找到对应的python版本和系统版本下载
随便放在哪里 记得就行 然后 pip install 刚才那个文件的绝对路径

安装ffmpeg工具

官网:https://www.gyan.dev/ffmpeg/builds/

找其中一个链接安装 完后解压出来
(想用代码操作的话 可以再安装 pip install ffmpeg-python -i https://pypi.douban.com/simple)

说明文档官网:什么终端操作命令都可以在里面学习查找
https://ffmpeg.org/documentation.html

下载

在这里插入图片描述

解压:

在这里插入图片描述
进入文件夹 获取bin的路径 加到环境变量
在这里插入图片描述

添加环境变量

在这里插入图片描述

代码总结

pydub 音频的播放和使用
# http://pydub.com/  文档链接
# 使用pydub 需要安装pyaudio ffmpeg
from pydub import AudioSegment

from pydub.playback import play

# 加载音频
# song = AudioSegment.from_mp3("李白.mp3")
# 以自定义的格式 加载视频 或 音频也可以
# song = AudioSegment.from_file("视频.mp4", format="mp4")
# 加载音频 后 转化为别的格式
song = AudioSegment.from_file("20210802_093119.m4a", format="m4a")
song.export("防疫.mp3", format="mp3")

# 播放音频
# play(song)

opencv 图片操作(可中文路径)
import cv2
import numpy as np



# 直接以RGB模式读取图像
img = cv2.imread('wang.png',cv2.IMREAD_COLOR)
# 写入本地图片
cv2.imwrite("wang23.jpg".encode("gbk").decode("utf8",errors="ignore"),img)

# 将BGR模式转化为RGB模式
# cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 下面可以读取含中文名字的图片 -1 RGB模式
img = cv2.imdecode(np.fromfile('王心凌.png',dtype=np.uint8),-1)
# 将使用imdecode读取图片数据写入本地
cv2.imencode('.png', img)[1].tofile("王心凌2.png")


img_mask = ~frame  # 图像反色
# 图像二值化 大于阈值 threshold_value 的都设置为 255 即纯白色 小于阈值的设置为纯黑色
threshold_value = 2
# T 代表阈值  img_threshold 是处理完的图像
(T, img_threshold) = cv2.threshold(img_mask, threshold_value, 255, cv2.THRESH_BINARY)

# 窗口设置 cv2.WINDOW_NORMAL 可调节大小
cv2.namedWindow("窗口名字",cv2.WINDOW_NORMAL)
# 许多文字还是无法正确显示
cv2.imshow('窗口名字'.encode("gbk").decode("utf8",errors="ignore"), img)

c = cv2.waitKey(1000)  # 等待1秒 让用户输入 
if c == 27:  # 当键盘按下‘ESC’退出程序 结束视频的写入
    # new_video.release()
    cv2.destroyAllWindows()
    print('程序被主动操作结束 按下了esc')
    #break
cv2.destroyAllWindows()
opencv 基本绘图
# 导入相关库
import cv2 as cv, numpy as np
# from matplotlib import pyplot as plt
import matplotlib.pyplot as plt     # 上下两种引入方式都可以
 
# 画图实现代码
"""
1.画线,要绘制一条线,您需要传递线的开始和结束坐标。
我们将创建一个黑色图像,并从左上角到右下角在其上绘制一条蓝线。"""
# 创建黑色图像,这个3是表示是三维数组的意思,如果是灰色图像则不用写3。
# 三维数组指的是彩色图像,每个像素点除了位置信息,还有RGB通道选择。
img = np.zeros((512, 512, 3), np.uint8)
# print(img)
# 绘制一条厚度为5的蓝色对角线,起止坐标:(0, 0), (511, 511),颜色(BGR):(255, 0, 0),厚度:5
cv.line(img, (0, 0), (511, 511), (255, 0, 0), 5)
cv.line(img, (511, 0), (0, 511), (255, 0, 0), 5)
 
# 2.画矩形,需要矩形的左上角和右下角坐标,在图像的右上角绘制一个绿色矩形。
cv.rectangle(img, (206, 206), (306, 306), (0, 255, 0), 3)
 
# 3.画圆,需要中心坐标(256, 256)和半径50,在上面绘制的矩形内绘制一个红色(0, 0, 255)的实心(-1)圆。
cv.circle(img, (256, 256), 50, (0, 0, 255), -1)
 
"""
4.画椭圆,参数1:是中心位置坐标(256, 256)。参数2:是轴长度(长轴长度,短轴长度)(100, 50)
参数3:角度angle是椭圆沿逆时针方向旋转的角度。参数4:startAngle和endAngle表示从主轴
沿顺时针方向测量的椭圆弧的开始和结束,参数5:颜色,参数6:线粗(-1指铺满)"""
cv.ellipse(img, (256, 256), (240, 80), 0, 0, 360, (255, 125, 89), 3)
cv.ellipse(img, (256, 256), (240, 80), 90, 0, 360, (255, 125, 89), 3)
cv.ellipse(img, (256, 256), (240, 80), 45, 0, 360, (255, 125, 89), 3)
cv.ellipse(img, (256, 256), (240, 80), -45, 0, 360, (255, 125, 89), 3)
 
# 5.画多边形,要绘制多边形,首先需要顶点的坐标。将这些点组成形状为 ROWSx1x2 的数组,
# 其中 ROWS 是顶点数,并且其类型应为int32。若第三个参数为False,将获得一条连接所有点的折线,而不是闭合形状
pts = np.array([[236, 25], [276, 25], [296, 50], [216, 50]], np.int32)
pts = pts.reshape((-1, 1, 2))
cv.polylines(img, [pts], True, (0, 255, 255), 5)    # 颜色(0, 255, 255),线条厚度5
 
# 5.向图像添加文本:参数:参数1.您要写入的文字数据,参数2.您要放置它的位置坐标(即数据开始的左下角)
# 参数3.字体类型(检查**cv.putText**文档以获取受支持的字体):font,参数4.字体比例:2(指定字体大小)
# 其他参数:例如颜色:(234, 123, 137),厚度:3,线条类型:cv.LINE_AA等。
font = cv.FONT_HERSHEY_SIMPLEX  # 字体类型
cv.putText(img, "JCY_OpenCV", (60, 500), font, 2, (234, 123, 137), 3, cv.LINE_AA)
 
# 打印图像
cv.imshow("pic", img)   # 显示画图结果
cv.waitKey(0)           # 窗口按键等待
cv.destroyAllWindows()  # 销毁打开的所有窗口
opencv视频操作
old_video_path ="xin_ling_no_bag.mp4"  # 原始视频路径
new_video_path = old_video_path.replace(".", "_词云视频.")  # 将来要存储的新视频路径
# 定义用于展示画面的窗口 设置名字 和 可调节大小的属性
window_name = "video_to_wordcloud_pic"
cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)

# cv2.namedWindow('window_name2', cv2.WINDOW_AUTOSIZE)
# cv2.namedWindow('window_name3', cv2.WINDOW_AUTOSIZE)
# 捕获视频文件
capture = cv2.VideoCapture(old_video_path)
# 帧率
fps = int(round(capture.get(cv2.CAP_PROP_FPS)))
# 当前帧数
current_frame = 100
# 总帧数
total_frame = int(capture.get(cv2.CAP_PROP_FRAME_COUNT))
# 分辨率-宽度
width = int(capture.get(cv2.CAP_PROP_FRAME_WIDTH))
# 分辨率-高度
height = int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 视频的图像的尺寸  可以使用cv2.resize(图像,尺寸)进行修改
size = (width, height)
# 设置跳转到的具体帧数
capture.set(cv2.CAP_PROP_POS_FRAMES, 120)
# 创建视频编辑对象.avi 文件
new_video = cv2.VideoWriter(new_video_path, cv2.VideoWriter_fourcc('X', 'V', 'I', 'D'), fps,size)
while capture.isOpened():
    ret, frame = capture.read()  # 每次循环都会去读取下一帧图像
    if ret:  # 如果读取到了图片
        img_mask = ~frame  # 图像反色 
        new_video.write(img)
        c = cv2.waitKey(1)
        # c = cv2.waitKey(0)  # 不限时间等待
        if c == 27:  # 当键盘按下‘ESC’退出程序 结束视频的写入
            # new_video.release()
            cv2.destroyAllWindows()
            print('程序被主动操作结束 按下了esc')
            break
# 同一个画面里堆叠显示多张图像
def show_multi_imgs(imglist):
    # 使用numpy的水平堆叠和竖直堆叠完成所有图像的堆叠,最后多张图在一个画面中一起显示
    if imglist[0].shape[0] < imglist[0].shape[1]:
        result = np.hstack((imglist[0], imglist[1]))  # 水平堆叠
    else:
        result = np.vstack((imglist[0], imglist[1]))  # 竖直堆叠

    return result
opencv 视频的播放
import numpy as np
import cv2

cap = cv2.VideoCapture('caiwenji.mp4')

while (cap.isOpened()):
    ret, frame = cap.read()
    cv2.imshow('frame', frame)
    if cv2.waitKey(40) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()
opencv 写入参数介绍

(‘I’, ‘4’, ‘2’, ‘0’) 编码是真的大啊 40M 的写完变成9个G
推荐(‘X’, ‘V’, ‘I’, ‘D’)相对大小在2倍以内

#创建视频流写入对象,VideoWriter_fourcc为视频编解码器,20为帧播放速率,(640,480)为视频帧大小

videoWriter = cv2.VideoWriter('video.avi', cv2.VideoWriter_fourcc('I', '4', '2', '0'), 20, (640,480))

#向视频文件写入一帧

videoWriter.write(frame)

#详解cv2.VideoWriter_fourcc对象(摘自Learning OpenCV3 Computer Vision with Python,坦白讲不太懂)

#fourcc意为四字符代码(Four-Character Codes),顾名思义,该编码由四个字符组成,下面是VideoWriter_fourcc对象一些常用的参数,注意:字符顺序不能弄混

#cv2.VideoWriter_fourcc('I', '4', '2', '0'),该参数是YUV编码类型,文件名后缀为.avi

#cv2.VideoWriter_fourcc('P', 'I', 'M', 'I'),该参数是MPEG-1编码类型,文件名后缀为.avi

#cv2.VideoWriter_fourcc('X', 'V', 'I', 'D'),该参数是MPEG-4编码类型,文件名后缀为.avi

#cv2.VideoWriter_fourcc('T', 'H', 'E', 'O'),该参数是Ogg Vorbis,文件名后缀为.ogv

#cv2.VideoWriter_fourcc('F', 'L', 'V', '1'),该参数是Flash视频,文件名后缀为.flv

在这里插入图片描述

ffmpeg合并音频和视频
import ffmpeg
input_video = ffmpeg.input('./new_video_0419.avi')
input_audio = ffmpeg.input("1-1 如何选择涨粉快的图文内容方向.mp4")

print("正准备合并")
ffmpeg.concat(input_video, input_audio, v=1, a=1).output('./finished_video.mp4').run()
print("合并完成")
压缩视频

直接输入 然后原分辨率输出 即可 默认大概有10倍的压缩率 视频画质依旧清晰

ffmpeg -i input.mp4 -y output.mp4
修改视频分辨率

scale=宽:高 宽和高有一个值可以设置为负数 比如 -1 代表等比例适应另一个值,写法紧凑不要有空格

ffmpeg -i input.mp4 -vf scale=1080:1920 -y output.mp4
格式转换

直接输入源文件,修改后缀作为输出文件即可,例如MP4转gif:

ffmpeg -i test.mp4 test.gif

简单批量转换

# 将wmv文件转化为mp4格式
import os
# 此代码的文件创建在和视频文件同样的文件夹下 如需更改 可以向os.listdir()中添加路径参数
for x in os.listdir():
    if os.path.splitext(x)[-1] == ".wmv" and os.path.splitext(x)[0]+".mp4" not in os.listdir():
        os.system(f"ffmpeg -i {x} {os.path.splitext(x)[0]}.mp4")
        print(x,"ok")
print("转化完毕")
视频变速

视频转为两倍速:

ffmpeg -i input.mp4 -an -filter:v "setpts=0.5*PTS" output.mp4

更改速度:将0.5修改为想要的倍数的倒数

改变视频帧率

通过输出配置-r设置,例如将输入视频转换为10帧率的输出视频

ffmpeg -i input.mp4 -r 10 output.mp4
视频剪辑

例如,从第30秒开始,截一分钟:

ffmpeg -ss 00:00:30 -t 60 -i src.mp4 -codec copy out.mp4
视频旋转
上下翻转 ffmpeg -i input.mp4 -vf vflip out.mp4
左右翻转 ffmpeg -i input.mp4 -vf hflip out.mp4
顺时针90° ffmpeg -i input.mp4 -vf transpose=1 out.mp4
逆时针90° ffmpeg -i input.mp4 -vf transpose=2 out.mp4
视频尺寸裁剪
ffmpeg -i input.mp4 -vf crop=1280:720:0:120 out.mp4

crop后的参数,宽:高:起始x:起始y

音频的切割
1、按固定时间等分切割
from pydub import AudioSegment
from pydub.utils import make_chunks

# 载入本地文件 
audio = AudioSegment.from_file("shuai_lin0928.mp3", "mp3")

size = 20*1000  # 设置切割每块的毫秒数 

chunks = make_chunks(audio, size)  ##将文件按 size 毫秒一块 进行切割

for i, chunk in enumerate(chunks):
    ##枚举,i是索引,chunk是切割好的文件
    chunk_name = "shuai_lin{}.wav".format(i)
    print(chunk_name)
    # 保存文件
    chunk.export("outvoice/"+chunk_name, format="wav")
2、 按音频的静默间隔进行切割

也就是自由设置,当声音中断多久的时候,咔嚓来一刀切开

from pydub import AudioSegment
from pydub.silence import split_on_silence

sound = AudioSegment.from_mp3("shuai_lin0928.mp3")
loudness = sound.dBFS
# print(loudness)

chunks = split_on_silence(sound,
                          # must be silent for at least half a second,沉默半秒
                          min_silence_len=430,
                          # consider it silent if quieter than -16 dBFS
                          silence_thresh=-45,
                          keep_silence=400

                          )
print('总分段:', len(chunks))

# 放弃长度小于2秒的录音片段
# for i in list(range(len(chunks)))[::-1]:
#     if len(chunks[i]) <= 1000 or len(chunks[i]) >= 10000:
#         chunks.pop(i)
# print('取有效分段(大于2s小于10s):', len(chunks))

'''
for x in range(0,int(len(sound)/1000)):
    print(x,sound[x*1000:(x+1)*1000].max_dBFS)
'''

for i, chunk in enumerate(chunks):
    chunk.export("cut_single/chunk{0}.wav".format(i), format="wav")
带参数读取
from pydub import AudioSegment

sound = AudioSegment.from_mp3('shuai_lin0928.mp3')
# 获取原始pcm数据

# data=sound.raw_data
data = sound._data

sound_wav = AudioSegment(
    # 指定原始pcm文件
    # raw audio data (bytes)
    data=data,

    # 指定采样深度,可选值1,2,3,4
    # 2 byte (16 bit) samples
    sample_width=2,

    # 指定采样频率
    # 44.1 kHz frame rate
    # 16kHz frame rate
    frame_rate=16000,

    # 指定声道数量
    # stereo or mono
    channels=1
)
# 导出wav文件
sound_wav.export('shuai_lin0928.wav', format='wav')

音频切片方法

像平时取切片一样即可 切片起始值的单位:毫秒

from pydub import AudioSegment
import pydub
from pydub.silence import split_on_silence

filename = 'shuai_lin0928.mp3'
audio_segment = AudioSegment.from_file(filename, format='mp3')

total = int(audio_segment.duration_seconds / 10) + 1  # 计算音频切片后的个数
for i in range(total):
    # 将音频10s切片,并以顺序进行命名
    audio_segment[i * 10000:(i + 1) * 10000].export("ouput/chunk{0}.wav".format(i), format="wav")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值