nanopc-T4 开发板通过USB麦克风采集录制音频
1. 使用 nanopc-T4 开发板采集音频
使用开发板采集音频时,总是报错,通过查阅很多资料后,逐渐有了一些头绪。
- 使用
arecord -l
命令可以查看当前系统的录音设备。
由此可以看出,当前系统有两个 USB Audio 设备,分别为 Tyless 外置录音和 C920 摄像头自带的录音设备。
root@NanoPC-T4:/home/pi/projects/nanopc/nanopc2jetlinks4mqtt# arecord -l
**** List of CAPTURE Hardware Devices ****
card 0: realtekrt5651co [realtek,rt5651-codec], device 0: ff880000.i2s-rt5651-aif1 rt5651-aif1-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
card 3: Tyless [Tyless], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 4: C920 [HD Pro Webcam C920], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
- 使用指定声卡录音
root@NanoPC-T4:/home/pi/projects/nanopc/nanopc2jetlinks4mqtt# sudo arecord -D hw:4 -d 40 test.wav -r16000 -fS16_LE -c 2
Recording WAVE 'test.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Mono
-D 表示指定设备,hw:x 表示第x个设备(使用命令 arecord -l 查看)
-d 表示时间,单位为秒
'test.wav' 为录音保存的文件名
-r 表示设置频率
-f 为设置格式
-c 表示通道数
2. 使用 Tyless 录制声音
使用 arecord -l 查看 tyless 的设备号,input_device_index=3
设置频率 rate 为48000Hz
设置通道数 CHANNELS 为 1
具体代码如下(测试通过):
# name:008.py
#录制音频
import wave
import pyaudio
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
# RATE = 44100
RATE = 48000
#RATE = 22050
RECORD_SECONDS =30
p = pyaudio.PyAudio()
#i=0
while True:
#i=i+1
# 数据流
stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True,input_device_index=3, frames_per_buffer=CHUNK)
print("开始录音!")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK,exception_on_overflow = False)
frames.append(data)
print("录音完毕!")
# 停止数据流
stream.stop_stream()
stream.close()
# 关闭PyAudio
#p.terminate()#不能这样操作,否则会出现不能循环的现
# 写入录音文件
wf = wave.open('011.wav', 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
print('音频数据写入完成')
break;
具体代码 :https://gitee.com/qiaoyukeji/nanopc2jetlinks4mqtt/blob/master/test_005_audio/008.py
3. 使用 ffrmpeg 将实时视频与音频合并并推流到 rtmp 服务器中
ffmpeg \
-f alsa -ac 2 -i hw:4,0 -r 48000 \
-f v4l2 -r 10 -i /dev/video0 \
-c:v libx264 -s 640x480 -pix_fmt yuv420p -preset ultrafast -g 20 -b:v 2500k \
-c:a aac -ar 44100 \
-threads 0 -bufsize 512k \
-f flv rtmp://iot.gitnote.cn/live/test &> stream.log
-f fmt 指定格式(音频或视频格式)
-ac channels 设置声道数
-i filename 指定输入文件名,在linux下当然也能指定:0.0(屏幕录制)或摄像头
-r rate 桢速率(fps)
-vcodec codec 强制使用codec编解码方式(copy to copy stream)
-acodec codec 指定音频编码(copy to copy stream)
-pix_fmt format 设置像素格式,“列表”作为参数显示所有支持的像素格式
-g int 设置图像组大小
-b 指定比特率(bits/s),似乎ffmpeg是自动VBR的,指定了就大概是平均比特率
-ar rate 设置音频采样率 (单位:Hz)
具体参数含义见:https://www.scivision.dev/youtube-live-ffmpeg-livestream/
4. 成功实现opencv采集图像与音频合并推送到rtmp
图像使用opencv调用摄像头采集并处理
音频使用 alsa 在 ffmpeg 命令行中采集
然后合并推送远程rtmp服务器中
相关代码见:https://gitee.com/qiaoyukeji/nanopc2jetlinks4mqtt/blob/master/test_005_audio/rtmp_001.py
# 本代码实现 opencv 采集视频并使用ffmpeg与音频audio合并推送到远程 rtmp 服务器中
# rtmp_001.py
# 需先自行安装FFmpeg,并添加环境变量
import cv2
import subprocess
import datetime
import numpy as np
from PIL import Image, ImageDraw, ImageFont
# RTMP服务器地址
# rtmp = r'rtmp://156756.livepush.myqcloud.com/live/test'
# rtmp = r'rtmp://172.17.14.191/live/test'
rtmp = r'rtmp://iot.gitnote.cn/live/test'
# 读取视频并获取属性
cap = cv2.VideoCapture(0)
cap.set(3, 640) # set video widht
cap.set(4, 480) # set video height
size = (int(640), int(480))
sizeStr = str(size[0]) + 'x' + str(size[1])
command = ['ffmpeg',
'-y', # -y 覆盖已有文件
"-thread_queue_size","102400", # 封装队列大小
########### 音频采集相关参数
'-f', 'alsa', # -f fmt 指定格式(音频或视频格式)
'-ac', '2', # -ac channels 设置声道数
'-i', 'hw:3,0', # -i filename 指定输入文件名,在linux下当然也能指定:0.0(屏幕录制)或摄像头
############ 视频处理相关参数
# '-f', 'v4l2',
'-f', 'rawvideo', # -f fmt 指定格式(音频或视频格式)
'-vcodec','rawvideo', # -vcodec codec 强制使用codec编解码方式
'-pix_fmt', 'bgr24', # -pix_fmt format 设置像素格式,“列表”作为参数显示所有支持的像素格式
'-s', sizeStr, # -s size 分辨率
'-r', '25', # -r rate 桢速率(fps)
'-i', '-',
'-c:v', 'libx264',
'-pix_fmt', 'yuv420p',
'-preset', 'ultrafast',
'-b:v','2000k',
'-c:a', 'aac', # 设置音频格式
'-ar', '44100', # -ar rate 设置音频采样率 (单位:Hz)
"-threads","2",
"-bufsize","1024k",
'-f', 'flv',
rtmp]
pipe = subprocess.Popen(command, shell=False, stdin=subprocess.PIPE)
font = cv2.FONT_ITALIC # 字体
fourcc = cv2.VideoWriter_fourcc(*'XVID') #定义编解码器并创建VideoWriter对象,即输入四个字符代码即可得到对应的视频编码器(XVID编码器)
out = cv2.VideoWriter('video1.avi', fourcc, 20.0, (640,480)) #参数:保存文件名,编码器,帧率,视频宽高
# 图片帧添加文字函数
def cv2ImgAddText(img, text, left, top, textColor=(0, 255, 0), textSize=20):
if (isinstance(img, np.ndarray)): # 判断是否OpenCV图片类型
img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
# 创建一个可以在给定图像上绘图的对象
draw = ImageDraw.Draw(img)
# 字体的格式
fontStyle = ImageFont.truetype(
"simsun.ttc", textSize, encoding="utf-8")
# 绘制文本
draw.text((left, top), text, textColor, font=fontStyle)
# 转换回OpenCV格式
return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
while cap.isOpened():
success, frame = cap.read()
cv2.putText(frame,(datetime.datetime.utcnow() + datetime.timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S'), (15,40),font , 1, (255,255,255), 2)
# cv2.putText(frame,'安徽农业大学智慧养殖平台:HF-001 ', (15,400),font , 1, (255,255,255), 2)
# frame=cv2ImgAddText(frame,"安徽农业大学智慧养殖平台:HF-XX-001",15,50,(255,255,255),24)
if success:
if cv2.waitKey(1) & 0xFF == ord('q'):
break
pipe.stdin.write(frame.tostring())
out.write(frame)
cap.release()
pipe.terminate()
cv2.destroyAllWindows()