日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

最终屏幕录制方案

發布時間:2023/12/15 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 最终屏幕录制方案 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

屏幕錄制方案

需求

  • 實現任務錄制任務下發后自動將動畫和音頻錄制為MP4的視頻
  • 后臺服務
  • 錄制進度實時更新
  • 后續分享到視頻播放平臺,如愛奇藝、抖音等

方案架構

  • django command啟動服務
  • gearman提交下發任務
  • 后端采用PyQt5搭建服務平臺
  • QProcess執行ffmpeg錄制屏幕命令
  • QThread維持gearmanworker接受任務
  • WebDriver加載定制頁面播放動畫及音頻

前端

  • 實現動畫加載,圖片按瀏覽器寬高比率放置
  • 加載完成之后修改特定標簽文本值
  • 點擊事件觸發以后播放音頻,后續頁依次自動播放
  • 整個動畫文件播放完畢以后修改特定標簽文本值

后端

  • 搭建服務平臺
  • 執行ffmpeg錄制屏幕
  • 維持gearmanworker運轉,接收屏幕錄制任務
  • 監測前端錄制進程,控制錄制的開始和結束
  • 實時上傳錄制進度
  • 上傳視頻至cos

錄制流程圖

錄制流程說明

搭建服務平臺

django manage 啟動任務,初始化PyQT5搭建的服務平臺

class?Command(BaseCommand):

????def?handle(self,?*args,?**options):
????????app?=?QApplication(sys.argv)
????????win?=?MainWindow()
????????app.exit(app.exec_())

在PyQt5平臺中初始化

?參數(init_arguments)、搭載gearmanworker的(init_worker),WebDriver(init_driver),任務加載定時器(init_timer)

class?MainWindow(QMainWindow):

????def?__init__(self,?parent=None):
????????super(MainWindow,?self).__init__(parent)
????????self.root_path?=?Path(__file__).parent
????????self.setWindowTitle('易哈佛')
????????self.init_arguments()
????????self.init_driver()
????????self.init_worker()
????????self.init_timer()

注冊gearmanworker

QThread中注冊gearmanworker到gearman服務器,接收到的任務都存入任務池中

class?WebWorker(QThread):

????def?__init__(self):
????????super().__init__()
????????self.worker?=?None
????????self.task_pool?=?[]

????def?run(self):
????????self.worker?=?self.init_worker()
????????self.worker.work()

????def?init_worker(self):
????????convert_worker?=?JsonWorker(['c.ehafolive.com:4730',?])
????????convert_worker.set_client_id('capture')
????????convert_worker.register_task('screencapture',?self.task_listener)
????????return?convert_worker

????@property
????def?worker_(self)?->?JsonWorker:
????????return?self.worker

????def?task_listener(self,?gearman_worker,?request):
????????self.task_pool.append(request.data)

任務加載定時器

任務加載定時器會每五秒調起一次任務加載功能。任務加載功能必須在任務池存在任務,并且當前平臺沒有任務時才會執行任務加載,為了避免并發導致任務沖突,所以任務加載功能單線程執行。

def?load_url(self):
????#?接受視頻錄制任務
????self.lock.acquire()
????if?self.WebWorker.task_pool?and?self.usable:
????????self.usable?=?False
????????info?=?self.WebWorker.task_pool.pop(0)
????????self.video_layout?=?info.get('layout')
????????self.h_id?=?int(info.get('pk'))
????????print(self.video_layout,?self.h_id)
????????self.driver_load()
????self.lock.release()

瀏覽器加載功能

一但允許任務加載從任務池中提取一個任務,提取出數據,調用瀏覽器加載功能,瀏覽器加載功能是通過加載定制的頁面,并通過設置瀏覽器的位置和寬高來大致確定后續需要錄制的區域,在頁面加載完畢后,需要初始化錄制動作監控定時器,并初始化一個視頻對象,后續的進度實時更新依賴于初始化的視頻對象

def?driver_load(self):
????#?設置瀏覽器位置及窗口大小,加載url
????url?=?"https://xxxx?pk=%s"?%?self.h_id
????if?self.video_layout?==?'vertical':
????????width,?height?=?1000,?1446
????else:
????????width,?height?=?1373,?800
????self.set_driver(width,?height)
????self.driver.get(url)
????self.init_cmd_timer()
????self.init_video_instance()

瀏覽器設置

通過對任務的橫版和豎版的判定,將瀏覽器位置調整到合適的區域,并設置相應的寬高

def?set_driver(self,?width,?height):
????if?self.video_layout?==?'vertical':
????????left,?top?=?self.chose_screen(768,?1366)
????else:
????????left,?top?=?self.chose_screen(1366,?768)
????self.screen_width?=?width?-?self.window_offset_x
????self.screen_height?=?height?-?self.window_offset_y
????self.driver.set_window_position(left?-?self.window_offset_x,?top)
????self.driver.set_window_size(width,?height)

視頻對象的初始化

因為任務可能重復下發,因此視頻對象可能早有存在,所以對于已存在的對象只需局部更新數據,不需要另外創建

def?init_video_instance(self):
????from?article.models?import?Article
????from?points.models?import?Video
????queryset?=?Article.objects.filter(id=self.h_id)
????if?not?queryset.exists():
????????return
????article?=?queryset.first()
????data?=?{
????????'size':?0,
????????'process':?0,
????????'course':?self.h_id,
????????'user':?article.user,
????????'layout':?article.layout,
????????'duration':?article.duration,
????}
????video,?_?=?Video.objects.update_or_create(
????????defaults=data,
????????course=self.h_id,
????)
????self.video_id?=?video.id

錄制動作監控定時器超時事件響應

在上述任務加載完畢,并且初始化完成后,錄制動作監控定時器將迎來第一次的超時事件,超時事件將檢測相應的標簽值,在確定標簽值已經改變并由后端完成修改后,將調起相應的功能

#錄制動作監控定時器超時調起事件
def?monitor_cmd(self):
????if?self.set_monitor_tag_value('click'):
????????self.mouse_click_event()
????if?self.set_monitor_tag_value('start'):
????????self.start_capture()
????if?self.set_monitor_tag_value('stop'):
????????self.stop_capture()
#監測動作對應的標簽文本值,發生變化則進行修改
def?set_monitor_tag_value(self,?tag):
????lock?=?Lock()
????lock.acquire()
????_,?value?=?self.get_monitor_tag_value(tag)
????if?value?==?'false':
????????lock.release()
????????return?False
????attributeName?=?'textContent'
????js?=?"{}.{}={}".format(tag,?attributeName,?'false')
????self.driver.execute_script(js)
????print('set?element?value?%s'?%?tag)
????lock.release()
????return?True

click標簽文本值改變關聯事件

由后端在前端確定url加載完畢后調起,實現模擬點擊事件,通知前端開始播放動畫和音頻

def?mouse_click_event(self):
????#?點擊命令執行,開始播放
????self.driver.find_element_by_id('click-element').click()

start標簽文本值改變關聯事件

start標簽值的改變在前端確定動畫和音頻已經開始播放后修改,當后端檢測到文本值發生改變后,檢測錄制區域是否超出屏幕、初始化錄制視頻進程、初始化錄制進度更新定時器,開始屏幕錄制

def?start_capture(self):
????#?開始錄制視頻
????if?not?self.verify_capture_size():
????????return?self.unlocked()
????capture_cmd?=?self.init_capture_cmd()
????self.process?=?RecordProcess()
????self.process.start(capture_cmd)
????self.init_process_timer()
????print(capture_cmd)

stop標簽文本值改變關聯事件

start標簽值的改變在前端確定動畫和音頻已經播放完畢后修改,當后端檢測到文本值發生改變后,調起停止視頻錄制功能,關閉錄制動作監控定時器,關閉進度更新定時器,待錄制視頻進程完全結束,視頻文件生成后調起上傳視頻

def?stop_capture(self):
????#?停止錄制視頻
????if?not?hasattr(self,?'process'):?return
????self.process.quit()
????self.process_timer.stop()
????self.monitor_timer.stop()
????self.process.finished.connect(self.upload_video)

視頻上傳功能

上傳視頻到cos,上傳完成后,解除任務正在執行的標志,等待下一次任務加載,同時調起頂頂發送消息通知任務已經完成

def?upload_video(self):
????#?上傳視頻到數據庫
????url?=?save_video(self.video_path,?self.video_id)
????self.usable?=?True
????task_success(TASK,?"path:%s"?%?url)

上傳視頻

如果已經錄制過視頻,原視頻從cos刪除

def?save_video(video_path,?pk):
????if?not?os.path.exists(video_path):
????????print('視頻轉錄異常',?video_path)
????????return
????f?=?open(video_path,?'rb')
????url?=?upload_video(f.name,?f)
????f.seek(0)
????size?=?len(f.read())
????instance?=?Video.objects.get(id=pk)
????if?instance.url:
????????delete_from_cos(instance.url.url)
????instance.url?=?url
????instance.size?=?size
????instance.process?=?100
????instance.save()
????print(url,?pk)
????print('*'?*?100)
????f.close()
????return?url

??

轉載于:https://www.cnblogs.com/li1992/p/11057197.html

總結

以上是生活随笔為你收集整理的最终屏幕录制方案的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。