如何在Python中使用屏幕录制记录声音

3

我正在用Python制作屏幕录像,在这方面我成功地使用了Python PIL库来捕捉屏幕。

并在标签中显示它(当前录制)。

现在,当用户单击GUI窗口中的音频记录按钮时,我想记录用户的音频,并在用户单击停止记录音频按钮时停止记录声音。

最后,我希望将我的语音和视频录制合并为具有声音的最终输出视频

有人能告诉我如何将两个代码合并到一个脚本中,并成功运行它吗?

import datetime
import tkinter as tk
from tkinter import *
from tkinter import ttk ,FLAT
from PIL import Image, ImageTk, ImageGrab
import cv2
import numpy as np
import threading
import win32api
from tkinter.filedialog import asksaveasfilename


VIDEO_SIZE = (800,420)     #(960, 540)

cap = cv2.VideoCapture(0) 

date = datetime.datetime.now()
filename='rec_%s-%s-%s-%s%s%s.mp4' % (date.year, date.month, date.day,
                                                     date.hour, date.minute, date.second)

fourcc = cv2.VideoWriter_fourcc(*'H264')
frame_rate = 15

out = cv2.VideoWriter()
def change_i():
        if sound_btn.image == icon:
            start_recording()

            sound_btn.config(image=icon2)
            sound_btn.image = icon2
        else:
            stop_recording()

            sound_btn.config(image=icon)
            sound_btn.image = icon

def change_r():
        if rec_btn['text'] == 'Start Recording':
            start_recording()

            rec_btn.config(text="Stop Recoding")
        else:
            stop_recording()

            rec_btn.config(text="Start Recording")
def change_w():
        if cap_btn.image == web:
            start_webcam()

            cap_btn.config(image=web2)
            cap_btn.image = web2
        else:
            stop_webcam(None)

            cap_btn.config(image=web)
            cap_btn.image = web
# --- screen capture
def Cursor_pos(img,center,radius,color,thickness):
    center = tuple(map(int,center))
    rgb = [255*c for c in color[:3]] # convert to 0-255 scale for OpenCV
    alpha = color[-1]
    radius = int(radius)
    if thickness > 0:
        pad = radius + 2 + thickness
    else:
        pad = radius + 3
    roi = slice(center[1]-pad,center[1]+pad),slice(center[0]-pad,center[0]+pad)

    try:
        overlay = img[roi].copy()
        cv2.circle(img,center,radius,rgb, thickness=thickness, lineType=cv2.LINE_AA)
        opacity = alpha
        cv2.addWeighted(src1=img[roi], alpha=opacity, src2=overlay, beta=1. - opacity, gamma=0, dst=img[roi])
    except:
        logger.debug("transparent_circle would have been partially outside of img. Did not draw it.")

def recording_screen():

    global recording
    recording = True
    while recording:0,0.5), -1)
        #cv2.circle(frame, curpos, 10, (0,255,255), 2)
        frame = cv2.resize(frame, VIDEO_SIZE)
        tkimage.paste(Image.fromarray(frame))
        frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
        out.write(frame)

def start_recording():

    if not out.isOpened():
    out.open(filename, fourcc, frame_rate, VIDEO_SIZE)
    threading.Thread(target=recording_screen, daemon=True).start()

def stop_recording():
    global recording
    recording = False
    out.release()

# --- webcam

webcam = None
WEBCAM_SIZE = (280, 200)

def read_frame(imgbox):

    if cap.isOpened():
        ret, frame = cap.read()
        if ret:
            frame = cv2.flip(frame, 1)
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            frame = cv2.resize(frame, WEBCAM_SIZE)
            image = Image.fromarray(frame)
            imgbox.image.paste(image)
        webcam.after(20, read_frame, imgbox)

def stop_webcam(event):
    global webcam

    if webcam:
        webcam.destroy()
        webcam = None
        cap.release()
def start_webcam():
    global webcam

    if webcam is None:
        cap.isOpened()
        webcam = tk.Toplevel()
        #webcam = tk.lift()
        webcam.attributes("-topmost", True) #it keep the window on top of others
        webcam.geometry('{}x{}+5+520'.format(WEBCAM_SIZE[0], WEBCAM_SIZE[1]))
        webcam.overrideredirect(1)
        imgbox = tk.Label(webcam)
        imgbox.pack()
        imgbox.image = ImageTk.PhotoImage(image=Image.new('RGB',WEBCAM_SIZE,(0,0,0)))
        imgbox.config(image=imgbox.image)
        #webcam.bind('', stop_webcam)
        read_frame(imgbox)

# --- main

root = tk.Tk()
root.title('Screen Recorder')
#root.iconbitmap(r'rec_i.ico')  #for icon
root.resizable(width=False,height=False)
icon = PhotoImage(file='dh.png')
icon2 = PhotoImage(file='stop.png')
web = PhotoImage(file='webcam.png')
web2 = PhotoImage(file='webcamee.png')
root.geometry('+260+70')

tkimage = ImageTk.PhotoImage(Image.new('RGB', VIDEO_SIZE, (0,0,0)))


w, h = VIDEO_SIZE
vbox = tk.Label(root, image=tkimage, width=w, height=h, bg='black')
vbox.pack(pady=10,padx=25)

frame = tk.Frame(root)
frame.pack()

ound_btn = tk.Button(frame, image=icon, width=70,relief=FLAT ,command=change_i )
sound_btn.grid(row=0, column=1)
sound_btn.image = icon
cap_btn = tk.Button(frame, image=web, width=70,relief=FLAT, command=change_w)
cap_btn.grid(row=0, column=2)
cap_btn.image = web
message = Label(frame,text='**** press the start button to start recording ****')
message.grid(row=1, column=1)

root.mainloop()

我该怎么通过麦克风录制用户的声音同时录制屏幕呢?

有什么建议吗?

2个回答

1
你可以简单地记录屏幕以及同时录制声音。该代码将生成两个文件,一个是.mp4格式的视频文件,另一个是.mp3格式的音频文件。现在你已经准备好了... 将音频文件添加到视频文件中并保存到指定路径。

0
以下代码将帮助您同时开始屏幕录制和音频录制。然后,它将使用MoviePy库将音频和视频合并在一起。请注意,代码中用于视频录制的帧率和实际屏幕录制的帧率可能不同。此外,请注意MoviePy可能需要一些时间来处理音频和视频。
import pyautogui
import numpy as np
import cv2
import threading 
import sounddevice as sd
import queue
import soundfile as sf
from moviepy.editor import AudioFileClip, VideoFileClip
import tkinter as tk
from tkinter import messagebox
import time
class ScreenRecorderApp:
    def __init__(self, root):
          self.root = root
          self.root.title("Screen Recorder")
          self.start_button = tk.Button(root, text="Start Recording", command=self.start_recording)
          self.start_button.pack()
          self.stop_button = tk.Button(root, text="Stop Recording", command=self.stop_recording, state=tk.DISABLED)
          self.stop_button.pack()
          # Set up screen dimensions
          self.screen_width, self.screen_height = pyautogui.size()
          # Set up the codec and create a VideoWriter object
          self.fourcc = cv2.VideoWriter_fourcc(*"XVID")
          self.out = None
          # Set up audio parameters
          self.sample_rate = 44100  # CD quality
          self.audio_buffer = queue.Queue()
          # Flag to indicate recording state
          self.recording = False
          self.recording_thread = None

    def start_recording(self):
       self.recording = True
       self.out = cv2.VideoWriter("output_screen_recording.avi", self.fourcc, 20.0, (self.screen_width, self.screen_height))
       self.start_button.config(state=tk.DISABLED)
       self.stop_button.config(state=tk.NORMAL)
       # Start recording video in a separate thread
       self.start_time = time.time()  # Record start time
       self.num_frames = 0  # Initialize frame counter
       self.recording_thread = threading.Thread(target=self.record_screen)
       self.recording_thread.start()
       # Start recording audio
       with sd.InputStream(callback=self.record_audio, channels=2, samplerate=self.sample_rate):
           self.root.wait_window()  # Wait for the recording to finish 
    def stop_recording(self):
       self.recording = False
       self.recording_thread.join()
       self.out.release()
       self.save_audio()
       self.combine_audio_video()
       self.start_button.config(state=tk.NORMAL)
       self.stop_button.config(state=tk.DISABLED)
       messagebox.showinfo("Recording Finished", "Recording has been saved.")
    def record_screen(self):
       while self.recording:
           screenshot = pyautogui.screenshot()
           frame = np.array(screenshot)
           frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
           self.out.write(frame)
           self.num_frames += 1  # Increment frame counter 

    def record_audio(self, indata, frames, time, status):
       self.audio_buffer.put(indata.copy())
    def save_audio(self):
       audio_data = []
       while not self.audio_buffer.empty():
           audio_data.append(self.audio_buffer.get())
       audio_data = np.concatenate(audio_data, axis=0)
       sf.write("output_recorded_audio.wav", audio_data, self.sample_rate)
    
    def combine_audio_video(self):
       video_clip = VideoFileClip("output_screen_recording.avi")
       audio_clip = AudioFileClip("output_recorded_audio.wav")

       # Calculate the actual frame rate based on recorded frames and elapsed time
       actual_frame_rate = self.num_frames / (time.time() - self.start_time)
    
       final_clip = video_clip.set_audio(audio_clip)
       final_clip = final_clip.set_duration(audio_clip.duration)  # Adjust duration
       final_clip = final_clip.set_fps(actual_frame_rate)  # Set the calculated frame rate
       final_clip.write_videofile("output_video.mp4", codec="libx264")
root = tk.Tk()
app = ScreenRecorderApp(root)
root.mainloop()   

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接