|
|
"""
|
|
|
使用ffmpeg录制屏幕,并结合Pyaudio同步录制的音频合成带有声音的视频文件
|
|
|
"""
|
|
|
import sys
|
|
|
from pathlib import Path
|
|
|
from time import sleep
|
|
|
|
|
|
import ffmpeg
|
|
|
|
|
|
|
|
|
def file_path(filename):
|
|
|
relative_path = Path('resource').joinpath(filename)
|
|
|
if getattr(sys, 'frozen', False):
|
|
|
base_path = Path(sys._MEIPASS)
|
|
|
else:
|
|
|
base_path = Path('.').absolute()
|
|
|
return Path(base_path).joinpath(relative_path).as_posix()
|
|
|
|
|
|
|
|
|
class Screenshot:
|
|
|
|
|
|
def __init__(self, width=1920, height=1080, fps=15):
|
|
|
self.width = width
|
|
|
self.height = height
|
|
|
self.fps = fps
|
|
|
self.process = None
|
|
|
self.ffmpeg_path = file_path('ffmpeg.exe')
|
|
|
|
|
|
def __call__(self, width, height, fps=None):
|
|
|
self.width = width
|
|
|
self.height = height
|
|
|
self.fps = fps if fps else self.fps
|
|
|
|
|
|
@staticmethod
|
|
|
def unlink(filename):
|
|
|
Path(filename).unlink()
|
|
|
|
|
|
def record(self, filename, offset_x=0, offset_y=0, draw_mouse=0):
|
|
|
self.process = (
|
|
|
ffmpeg.output(
|
|
|
ffmpeg.input(
|
|
|
filename='desktop', format='gdigrab', framerate=self.fps, offset_x=offset_x, offset_y=offset_y,
|
|
|
draw_mouse=draw_mouse, s=f'{self.width}x{self.height}'),
|
|
|
filename=filename, pix_fmt='yuv420p'
|
|
|
).overwrite_output()
|
|
|
)
|
|
|
self.ffmpeg_async()
|
|
|
|
|
|
def compose_audio(self, video_path, audio_path, output_path):
|
|
|
self.process = (
|
|
|
ffmpeg.output(
|
|
|
ffmpeg.input(filename=video_path),
|
|
|
ffmpeg.input(filename=audio_path),
|
|
|
filename=output_path, vcodec='copy', acodec='aac', strict='experimental', pix_fmt='yuv420p'
|
|
|
).overwrite_output()
|
|
|
)
|
|
|
sleep(1)
|
|
|
self.ffmpeg_async()
|
|
|
|
|
|
def ffmpeg_async(self):
|
|
|
self.process = self.process.run_async(cmd=self.ffmpeg_path, pipe_stdin=True, pipe_stdout=False,
|
|
|
pipe_stderr=False)
|
|
|
|
|
|
def terminate(self):
|
|
|
if self.process is not None:
|
|
|
self.process.communicate(str.encode("q"))
|
|
|
self.process.terminate()
|
|
|
self.process = None
|