吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1834|回复: 40
收起左侧

[Python 原创] python写的一个录屏录音工具

  [复制链接]
heguang 发表于 2024-9-28 16:22
注册吾爱半年多了,第一次发帖。由于水平太菜了,一直在白嫖别人的工具,前几天看见有人(@william0712 )用python写了一个录屏小工具,想起之前闲来没事的时候我也用gpt写了个类似的,今天正好有空就直接开源出来了。界面十分简单,默认是全屏录屏录音(第一次使用得手动开启电脑声音设置的立体声混音作为输入),勾选不录制扬声器系统声音后只录屏,如果想自定义区域录制要先选择自定义区域录屏,然后再点击开始录制即可。考虑到编程小白的存在,我把代码打包成exe放在文末了,已经尽力在虚拟环境下打包了,但是还是有点大,需要的话自取即可,第一次发帖,如有违规请审核大大提醒修改{:1_889:} 。录音录屏工具

[Python] 纯文本查看 复制代码
import tkinter as tk
from tkinter import ttk
import tkinter.messagebox as messagebox
import pyautogui
import cv2
import numpy as np
from datetime import datetime
import threading
import pyaudio
import wave
import os
from moviepy.editor import VideoFileClip, AudioFileClip

# 隐藏命令行
import win32console
import win32gui
win = win32console.GetConsoleWindow()
win32gui.ShowWindow(win, 0)

class Popup(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("设置")
        self.geometry("300x250")
        self.configure(bg="#333333")
        self.create_widgets()
        self.recording_area = None  # 初始化录制区域
        self.record_microphone = True  # 初始化打开麦克风

    def create_widgets(self):
        self.recording = False
        self.stop_event = threading.Event()  # 使用 Event 对象

        self.rec_button = tk.Button(self, text="开始录制", command=self.toggle_recording, bg="#333333", fg="white", borderwidth=2, relief="solid")
        self.rec_button.pack(pady=10)

        self.stop_button = tk.Button(self, text="停止录制", command=self.stop_recording, bg="#333333", fg="white", borderwidth=2, relief="solid", state=tk.DISABLED)
        self.stop_button.pack(pady=5)

        # 区域选择按钮
        self.select_area_button = tk.Button(self, text="选择录制区域", command=self.select_area, bg="#333333", fg="white", borderwidth=2, relief="solid")
        self.select_area_button.pack(pady=10)

        # 扬声器录制选项
        self.mic_checkbox = tk.Checkbutton(self, text="不录制扬声器系统声音", command=self.toggle_microphone, bg="#333333", fg="white", selectcolor="black")
        self.mic_checkbox.pack(pady=10)

    def toggle_microphone(self):
        # 切换麦克风录制的状态
        self.record_microphone = not self.record_microphone

    def select_area(self):
        # 打开一个全屏窗口,允许用户通过鼠标拖动选择区域
        self.selection_window = tk.Toplevel(self)
        self.selection_window.attributes('-fullscreen', True)
        self.selection_window.attributes('-alpha', 0.3)  # 半透明
        self.selection_window.config(bg="gray")

        self.canvas = tk.Canvas(self.selection_window, cursor="cross", bg="gray")
        self.canvas.pack(fill="both", expand=True)

        self.rect_id = None
        self.start_x = None
        self.start_y = None

        # 绑定鼠标事件
        self.canvas.bind("<ButtonPress-1>", self.on_mouse_down)
        self.canvas.bind("<B1-Motion>", self.on_mouse_drag)
        self.canvas.bind("<ButtonRelease-1>", self.on_mouse_up)

    def on_mouse_down(self, event):
        # 记录起点
        self.start_x = event.x
        self.start_y = event.y
        self.rect_id = self.canvas.create_rectangle(self.start_x, self.start_y, self.start_x, self.start_y, outline='red', width=2)

    def on_mouse_drag(self, event):
        # 动态更新矩形
        self.canvas.coords(self.rect_id, self.start_x, self.start_y, event.x, event.y)

    def on_mouse_up(self, event):
        # 记录终点并计算区域
        end_x = event.x
        end_y = event.y
        self.recording_area = (self.start_x, self.start_y, end_x - self.start_x, end_y - self.start_y)
        self.selection_window.destroy()
        messagebox.showinfo("信息", f"选择的录制区域为:{self.recording_area}")

    def toggle_recording(self):
        if not self.recording:
            self.start_recording()
        else:
            self.stop_recording()

    def start_recording(self):
        self.recording = True
        self.stop_event.clear()  # 清除事件状态
        frame_rate = 30
        timestamp = self.get_current_timestamp()
        self.video_filename = f"recorded_video_{timestamp}.mp4"
        self.audio_filename = f"recorded_audio_{timestamp}.wav"

        if self.recording_area is None:
            screen_width, screen_height = pyautogui.size()
            self.recording_area = (0, 0, screen_width, screen_height)  # 默认全屏

        codec = cv2.VideoWriter_fourcc(*"mp4v")
        self.video_out = cv2.VideoWriter(self.video_filename, codec, frame_rate, (self.recording_area[2], self.recording_area[3]))

        # 判断是否需要录制麦克风
        if self.record_microphone:
            # 声音录制线程
            self.audio_thread = threading.Thread(target=self.record_audio, args=(self.audio_filename,))
            self.audio_thread.start()

        # 启动录制线程
        self.recording_thread = threading.Thread(target=self.record_screen)
        self.recording_thread.start()

        self.rec_button.config(text="正在录制", state=tk.DISABLED)
        self.stop_button.config(state=tk.NORMAL)

    def record_screen(self):
        while not self.stop_event.is_set():  # 检查事件状态
            img = pyautogui.screenshot(region=self.recording_area)  # 录制自定义区域
            frame = np.array(img)
            frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
            self.video_out.write(frame)

        self.video_out.release()
        print("视频录制结束")

    def record_audio(self, filename):
        chunk = 1024
        sample_format = pyaudio.paInt16
        channels = 2
        fs = 44100  # 采样频率

        p = pyaudio.PyAudio()

        # 打开麦克风输入流
        stream = p.open(format=sample_format,
                        channels=channels,
                        rate=fs,
                        input=True,
                        frames_per_buffer=chunk)

        frames = []

        while not self.stop_event.is_set():  # 检查事件状态
            data = stream.read(chunk)
            frames.append(data)

        stream.stop_stream()
        stream.close()
        p.terminate()

        # 保存音频到 wav 文件
        with wave.open(filename, 'wb') as wf:
            wf.setnchannels(channels)
            wf.setsampwidth(p.get_sample_size(sample_format))
            wf.setframerate(fs)
            wf.writeframes(b''.join(frames))

        print("录音结束")

    def stop_recording(self):
        self.recording = False
        self.stop_event.set()  # 设定事件,结束录制

        if self.record_microphone:
            self.audio_thread.join()  # 等待音频线程结束

        if os.path.isfile('merged_video.mp4'):
            messagebox.showinfo("提示", "合并视频文件已保存至当前目录文件夹,想重新录制请删除原文件后重试!")
            # 更新按钮状态
            self.rec_button.config(text="请删除原文件后再开始录制", state=tk.NORMAL)
            self.stop_button.config(state=tk.DISABLED)
        else:
            # 合成音视频
            self.merge_audio_video()

    def merge_audio_video(self):
        merge_file = 'merged_video.mp4'

        video_clip = VideoFileClip(self.video_filename)

        if self.record_microphone:
            audio_clip = AudioFileClip(self.audio_filename)
            final_clip = video_clip.set_audio(audio_clip)
        else:
            final_clip = video_clip  # 如果没有录音,只保存视频

        final_clip.write_videofile(merge_file, codec='libx264', audio_codec="aac")

        # 删除录制的视频文件和音频文件
        os.remove(self.video_filename)
        if self.record_microphone:
            os.remove(self.audio_filename)

        print("音视频合成完成,存储为", merge_file)
        # 更新按钮状态
        self.rec_button.config(text="开始录制", state=tk.NORMAL)
        self.stop_button.config(state=tk.DISABLED)

    def get_current_timestamp(self):
        return datetime.now().strftime("%Y%m%d_%H%M%S")

if __name__ == "__main__":
    popup = Popup()
    popup.mainloop()

运行界面

运行界面

可勾选不录制扬声器系统声音

可勾选不录制扬声器系统声音

选择录制区域再点击开始录制

选择录制区域再点击开始录制

免费评分

参与人数 6吾爱币 +12 热心值 +6 收起 理由
crary06 + 1 我很赞同!
水雨争枫 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
ccxxtt + 1 + 1 感谢作者分享,能不能把系统声音和麦克声音分开打钩
anning666 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
william0712 + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

dzwxj 发表于 2024-11-11 10:42
本帖最后由 dzwxj 于 2024-11-11 10:52 编辑

测试了一下,才录制3分钟看了一下文件(应该是录制过程中文件(默认在当前目录下))就达250MB左右,这会影响录制的流畅性及最后存储收尾时的稳定性,弄不好最后停止会软件崩溃。一般用其它软件录制一小时最终的视频文件也就才一两百MB左右,最大也就一个GB(选择4K超清录制模式)。
另一个问题是,就录了3分钟,点停止录制,结果卡住了,半天停止不下来没法完成最终录制文件的写入,最后录制生成的最终文件打开看结束也就定格在“停止录制”界面死机这种状态下,哈哈。这说明在最后收尾时,对最终文件的写入完成存在一些有待优化的空间。因为我用的录制软件太多了,但基本上是点了停止立马结束。总之,PYTHON这个呢功能是强大,能做的事情也多,但真正在性能上达到用户的要求还是有一定差距的。毕竟这一部分压缩算法这些恰恰是它的弱项。虽然PYTHON的底层也是用别人的各种库,但毕竟是脚本语言,加上死丑的TK和低效率和差的稳定性,导致了一些不尽人意的设计。
 楼主| heguang 发表于 2024-9-29 13:17
链接好像没加进来,补个链接:https://wwjg.lanzouo.com/ijYNK2b2g8wh
密码:52pj
fast123 发表于 2024-9-29 19:07
wasm2023 发表于 2024-9-30 09:56
感谢分享
aodiming 发表于 2024-9-30 20:19
想入门,一直没有这种源代码参考,感谢分享
xiaolinge566 发表于 2024-10-1 11:42
感谢分享。
 楼主| heguang 发表于 2024-10-4 13:58

此问题目前已解决,有时间再更新一下帖子吧

本帖最后由 heguang 于 2024-10-4 14:36 编辑

今天才发现好像录制的视频音画不同步,有没有大神帮忙修复下
shuguang2121 发表于 2024-10-4 17:26
感谢分享
weiloveyuan 发表于 2024-10-8 11:04
刚好需要这款软件,感谢分享,谢谢
piazini 发表于 2024-10-9 22:33
都是大佬,啥工具都有
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-15 20:41

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表