Essayez de créer un logiciel de capture aussi précis que possible avec python (1)

introduction

OS:windows10 64bit python:3.7

Il existe des tonnes de logiciels qui peuvent enregistrer, Enregistrer l'écran d'un site Web spécifique à une heure spécifiée Parce qu'il n'y avait pas de logiciel capable de répondre à la demande super personnelle Je vais l'écrire en python comme s'il s'agissait d'un entraînement cérébral ludique.

Ce n'est pas aussi difficile que d'écrire des articles séparément, En raison des contraintes de temps, j'écrirai dans différentes parties.

En outre, divers problèmes survenus pendant le travail, C'est très redondant parce que j'écris sur la façon d'y faire face. Notez s'il vous plaît.

politique

Dans l'ensemble, supposons le flux suivant.

    1. Exécution de la commande à l'heure spécifiée
  1. Démarrez le navigateur avec l'URL prédéfinie
    1. Capturez les captures d'écran et l'audio du navigateur
  2. Sortie vidéo en fusionnant les captures d'écran du navigateur et l'audio

Cette page considère 3. Cela ressemble à une vérification rapide des célèbres bibliothèques de python Je n'ai rien trouvé qui puisse capturer à la fois l'image et le son. (Peut-être que si vous cherchez git. J'apprécierais que vous me le disiez.)

Je pense que c'est facile de tout faire avec ffmpeg, Cette fois, je vais l'essayer sous la liaison sans signification de l'exécuter sur du code python.

Capture audio

Je vais essayer d'utiliser le célèbre pyaudio.

Installez pyaudio

Selon la personne, ma main peut s'arrêter, alors je l'écrirai sous forme de mémo. Lors de l'installation de pyaudio, l'erreur suivante s'est produite dans mon environnement.

src/_portaudiomodule.c(29): fatal error C1083: include
Impossible d'ouvrir le fichier.'portaudio.h':No such file or directory

Il semble que l'outil de construction échoue. https://minato86.hatenablog.com/entry/2019/04/04/005929#portaudiohNo-such-file-or-directory Reportez-vous au lien ci-dessus et installez à partir du fichier whl correspondant à votre PC.

pip install PyAudio-0.2.11-cp37-cp37m-win_amd64.whl

Mon environnement d'exécution est pycham. Je cours dans un environnement virtuel de python. Même si vous exécutez la commande ci-dessus, elle sera sur le lecteur C Il ne sera installé que sur le python installé.

D:\~(Omission)~\venv\Scripts\activate.bat

Après avoir activé l'environnement virtuel en appuyant sur activate.bat à partir de l'invite de commande Dans cet état, j'ai frappé la commande ci-dessus pour l'installer.

Implémenté avec pyaudio

Maintenant que l'installation est terminée, enregistrons-la.

Un programme qui enregistre avec Python 3 et l'écrit dans un fichier wav
https://ai-trend.jp/programming/python/voice-record/

Je ne sais pas de quel type de bibliothèque il s'agit, donc je n'ai pas branché de microphone pour le moment Examinons la source de l'échantillon d'enregistrement sur ce site tel quel.

OSError: [Errno -9998] Invalid number of channels

Il s'est arrêté avec une erreur. Cette erreur est due à l'absence d'un périphérique d'entrée d'enregistrement. "Qu'essayez-vous d'enregistrer sans microphone?" Je suis en colère. Le input_device_index spécifié dans audio.open semble être incorrect. Vérifions le périphérique audio de votre ordinateur

import pyaudio
audio = pyaudio.PyAudio()
for i in range(audio.get_device_count()):
    dev = audio.get_device_info_by_index(i)
    print('name', dev['name'])
    print('index', dev['index'])
0 Microsoft Sound Mapper- Output, MME (0 in, 2 out)
<  1 BenQ GL2460 (NVIDIA High Defini, MME (0 in, 2 out)
   2 Realtek Digital Output (Realtek, MME (0 in, 2 out)
   5 Realtek Digital Output (Realtek High Definition Audio), Windows
DirectSound (0 in, 2 out)
   6 Realtek Digital Output (Realtek High Definition Audio), Windows WASAPI
(0 in, 2 out)
   ...
   ...
   ...
10 table de mixage stéréo(Realtek HD Audio Stereo input), Windows WDM-KS (2 in, 0 out)
12 Mike(Realtek HD Audio Mic input), Windows WDM-KS (2 in, 0 out)

J'y suis souvent allé. Ce n'est pas le cas car BenQ et Realtek Digital Output sont des périphériques de sortie ou des haut-parleurs. Je peux voir un microphone comme un périphérique d'entrée, Ceci est susceptible d'enregistrer la voix extérieure.

Lequel est susceptible d'entrer le son à l'intérieur de l'ordinateur?

10 table de mixage stéréo(Realtek HD Audio Stereo input), Windows WDM-KS (2 in, 0 out)

Le mixeur stéréo est une fonction qui donne le son à l'intérieur de l'ordinateur comme son d'entrée. Ici, sélectionnons "Stereo Mixer" et exécutons-le. (Il semble que vous puissiez le faire avec WASAPI, mais ignorez-le ici) Entrez le numéro du mélangeur stéréo dans l'index des périphériques et essayez de démarrer.

[Errno -9999] Unanticipated host error

Aussi une erreur. Je pense que cela fait également référence aux paramètres côté OS. Vérifions les paramètres côté OS

https://ahiru8usagi.hatenablog.com/entry/Windows10_Recording Panneau de configuration du son-> Onglet Enregistrement-> Activer le mixeur stéréo, Sélectionnez "Son" -> "Entrée" dans les fenêtres de la table de mixage stéréo.

J'ai donc pu enregistrer en toute sécurité. (Le code est dans le chapitre suivant)

Capture d'écran

Prenons une capture d'écran avec ImageGrab.

pip install Pillow

Enregistrement et capture audio simultanés

Enfin le code (prototype). Ce code a quelques problèmes, mais je le posterai comme un progrès.

import cv2
import numpy as np
from PIL import ImageGrab
import ctypes
import time
import pyaudio
import wave

#Enregistrer l'heure de début

# parentTime = time.time()
# for i in range(10):
#     img_cv = np.asarray(ImageGrab.grab())
# current = time.time()
# diff = (current - parentTime)
# print("fps:" + str(float(10)/diff))


user32 = ctypes.windll.user32
capSize = (user32.GetSystemMetrics(0), user32.GetSystemMetrics(1))

fourcc = cv2.VideoWriter_fourcc(*"DIVX")
writer = cv2.VideoWriter("test.mov", fourcc, 30, capSize)
count = 0
FirstFlag = True

WAVE_OUTPUT_FILENAME = "test.wav"
RECORD_SECONDS = 40

FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
CHUNK = 2 ** 11
audio = pyaudio.PyAudio()
stream = audio.open(format=FORMAT,
                    channels=CHANNELS,
                    rate=RATE,
                    input=True,
                    input_device_index=0,
                    frames_per_buffer=CHUNK)

frames = []

# #Enregistrer l'heure de début
# sTime = time.time()
# count = 0

print ("start")
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
    # count+=1
    # if count == 30 :
    #     current = time.time()
    #     diff = (current - sTime)
    #     print("fps:" +  str(float(count)/diff))
    #     sTime = time.time()
    #     count = 0

    #Capture d'image
    img_cv = np.asarray(ImageGrab.grab())
    img = cv2.cvtColor(img_cv, cv2.COLOR_BGR2RGB)
    writer.write(img)

    #Capture de voix
    data = stream.read(CHUNK)
    frames.append(data)
print ("finish")


writer.release()
stream.stop_stream()
stream.close()
audio.terminate()

waveFile = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
waveFile.setnchannels(CHANNELS)
waveFile.setsampwidth(audio.get_sample_size(FORMAT))
waveFile.setframerate(RATE)
waveFile.writeframes(b''.join(frames))
waveFile.close()

Code pour enregistrer séparément la vidéo (mov) et l'audio (wav). La durée d'enregistrement est de 40 secondes car il s'agit du nombre de secondes spécifié dans RECORD_SECONDS. Eh bien, quand j'essaye de faire ça, le résultat est. .. ..

Le fichier audio dure 39 secondes
Le fichier vidéo dure 28 secondes

Mis à part les fichiers audio Le fichier vidéo a donné un résultat très suspect.

writer = cv2.VideoWriter("test.mov", fourcc, 30, capSize)

J'ai défini le paramètre lors de l'enregistrement de la vidéo sur 30 selon le cas, mais Cette valeur semble incorrecte. Calculons approximativement le nombre de fps.

    if count == 30 :
        current = time.time()
        diff = (current - sTime)
        print("fps:" +  str(float(count)/diff))
        sTime = time.time()
        count = 0

Le résultat est d'environ fps14-19. Calcul que 14 à 19 images sont produites par seconde. Ce que vous pouvez imaginer comme le traitement effectué dans le contenu est, Pour les images de cadre à intervalles de 0,06 seconde Parce que la vidéo était sortie comme si elle venait à des intervalles de 0,03 seconde, Il semble que la vidéo a été avancée rapidement et que le temps était court.

writer = cv2.VideoWriter("test.mov", fourcc, 15, capSize)

Passer à fps15 et aux images trop tard ou trop tôt Vous pourrez peut-être résoudre le problème du temps en sautant et en écrivant.

Mais avant ça ... c'est lent. Même s'il peut être enregistré, il semble cliquetis.

Quelle est la cause du processus? Essayons d'accélérer chaque processus.

#ImageGrab seul
parentTime = time.time()
for i in range(40):
    img = ImageGrab.grab()
current = time.time()
diff = (current - parentTime)
print("fps:" + str(float(40)/diff))

#ImageGrab+numpy
parentTime = time.time()
for i in range(40):
    img_cv = np.asarray(ImageGrab.grab())
current = time.time()
diff = (current - parentTime)
print("fps:" + str(float(40)/diff))

Par conséquent

ImageGrab.grab()27fps seul,
ImageGrab.grab()20fps lors de la conversion de en numpy.
ImageGrab.grab()18fps avec conversion de en numpy et conversion RVB.

Je ne dis pas que ImageGrab.grab () est lent, mais c'est un peu un problème lorsque l'on considère le post-traitement.

Vous pouvez améliorer chaque processus de conversion, Essayez de trouver quelque chose de plus rapide que ImageGrab.grab () qui capture l'image.

https://stackoverrun.com/ja/q/3379877

Reportez-vous au site ci-dessus et essayez de sortir avec l'API Windows.

# windows_api
import win32gui, win32ui, win32con, win32api
hwin = win32gui.GetDesktopWindow()
width = 1920
height = 1080
left = win32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN)
top = win32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN)
hwindc = win32gui.GetWindowDC(hwin)
srcdc = win32ui.CreateDCFromHandle(hwindc)
memdc = srcdc.CreateCompatibleDC()
bmp = win32ui.CreateBitmap()
bmp.CreateCompatibleBitmap(srcdc, 1920, 1080)
memdc.SelectObject(bmp)

parentTime = time.time()
arr = []
for i in range(30):
    memdc.BitBlt((0, 0), (width, height), srcdc, (left, top),
win32con.SRCCOPY)
    arr.append(memdc)
current = time.time()
diff = (current - parentTime)
print("fps:" + str(float(30)/diff))
fps:48.752326144998015

fps48. C'est explosif. Cela semble intéressant, je vais donc le corriger avec la politique d'utilisation de cette api.

Je n'ai plus de temps donc la prochaine fois

Recommended Posts

Essayez de créer un logiciel de capture aussi précis que possible avec python (1)
Essayez de créer un logiciel de capture aussi précis que possible avec python (2)
Essayez de créer un code de "décryptage" en Python
Essayez de créer un groupe de dièdre avec Python
Faisons un outil de veille de commande avec python
Essayez d'exploiter Facebook avec Python
Comment rendre le sélénium aussi léger que possible
Essayez de vous connecter à qiita avec Python
Fractal pour faire et jouer avec Python
Essayez de créer foldl et foldr avec Python: lambda. Aussi mesure du temps
Essayez de résoudre un problème défini de mathématiques au lycée avec Python
Essayez de créer votre propre AWS-SDK avec bash
Essayez de résoudre le diagramme homme-machine avec Python
Essayez de dessiner une courbe de vie avec python
Je veux faire un jeu avec Python
Essayez de générer automatiquement des documents Python avec Sphinx
Essayez de rendre le client FTP le plus rapide avec Pythonista
Essayez de détecter les poissons avec python + OpenCV2.4 (inachevé)
J'ai essayé d'implémenter le tri par fusion en Python avec le moins de lignes possible
WEB grattage avec python et essayez de créer un nuage de mots à partir des critiques
Essayez de gratter avec Python.
Essayez de résoudre le livre des défis de programmation avec python3
Essayez de créer un module Python en langage C
Expliquez en détail comment créer un son avec python
Essayez le fonctionnement de la base de données avec Python et visualisez avec d3
Essayez de créer une API RESTful avec MVC à l'aide de Flask 1.0.2
Essayez d'extraire des mots à haute fréquence en utilisant NLTK (python)
Essayez de le faire avec GUI, PyQt en Python
J'ai essayé de créer diverses "données factices" avec Python faker
La première API à créer avec le framework Python Djnago REST
[AWS] Essayez d'ajouter la bibliothèque Python à la couche avec SAM + Lambda (Python)
Expérimentez pour créer un PDF indépendant pour Kindle avec Python
Essayez d'ouvrir une sous-fenêtre avec PyQt5 et Python
Essayez d'automatiser le fonctionnement des périphériques réseau avec Python
Créer une interface graphique aussi facilement que possible avec python [édition tkinter]
J'ai essayé de créer une interface graphique à trois yeux côte à côte avec Python et Tkinter
C'est Halloween donc je vais essayer de le cacher avec Python
Essayez de déchiffrer les caractères déformés dans le nom du fichier joint avec Python
Essayez de défier le sol par récursif
Connectez-vous à BigQuery avec Python
Capture de caméra avec Python + OpenCV
Essayez de comprendre Python soi
Essayez la sortie Python avec Haxe 3.2
Connectez-vous à Wikipedia avec Python
Publiez sur Slack avec Python 3
Rendre avec la syntaxe facile
Créez Puyopuyo AI avec Python
Essayez d'exécuter Python avec Try Jupyter
Basculer python vers 2.7 avec des alternatives
Écrire en csv avec Python
Essayez la reconnaissance faciale avec Python
J'ai essayé de faire mon propre BOT lycéenne avec le style Rinna avec LINE BOT (Python & Heroku)
[5e] J'ai essayé de créer un certain outil de type Authenticator avec python
Activé pour convertir PNG en JPG avec Pillow of Python
Rubyist a essayé de créer une API simple avec Python + bouteille + MySQL
[2nd] J'ai essayé de créer un certain outil de type Authenticator avec python