Help us understand the problem. What is going on with this article?

初めてのPython スクスタのMVを連続再生させる -曲リストのスクロール-

始めに

Pythonを自学するための題材にスクスタのMV連続再生機能を選んでは見たものの、出来上がったプログラムはMVのループ再生こそ出来るが、実際は一曲のみしか再生できず連続再生機能と言うにはお粗末すぎる物だった。

今回は再生終了後に曲リストを下に送る動作の実装をしてみます。

前回の記事:初めてのPython スクスタのMVを連続再生させる

設計

01.jpg

上記画像の赤枠の内側をクリックすれば曲送りができますが曲一覧を見ればわかるように、曲ごとに全く異なる上共通部分として使えそうな範囲も他の曲と被っているため一意な部分を選ぶのは難しそうです。
ここは先に画面内で確実に一意となる部分の座標を取得しそこからOffset分を加算した座標をクリックさせます。

上記画像の青枠で囲まれた部分を対象としました。

ソースコード

pydef.py
# coding:utf-8
MAIN_PATH:str=".\\MVPlay\\"
FILE_TYPE:str="*.png"

#引数用定数
FILES:int=0
FILEEVENTS:int=1
WAITTIME:int=2

#X,Y座標取得用定数
X:int=0
Y:int=1

#イベント定義用定数
CLICK:int=0
SWIPE:int=1
RECURE:int=2
EXIT:int=3

#ファイルイベント用定数
FILE:int=0
EVENT:int=1
ARG1:int=2
ARG2:int=3
ARG3:int=4

#ファイルイベントを定義
FILEEVENTS_MAIN:list=[
    #ファイル名とマッチした画像の時、座標が指定された値分Offsetされた位置をクリックする
    [".\\MVPlay\\03scroll.png",CLICK,[220,630],None,None]
]
pyfunc.py
# coding:utf-8
from pydef import*

#ファイルイベントを取得
def getFileEvent(fn:str,fev):
    for tmpl in fev:
        if tmpl[FILE]==fn:
            return tmpl
    return None

#画像認識が成功する度増え続け、全てのファイルが終わったら最初に戻る
def sequentialCount(i:int,maxcount:int):
    if i>=maxcount:
        return 0
    else:
        return i+1
main.py
# coding:utf-8
import pyautogui
import glob
import time
from pydef import*
from pyfunc import*

#イベントに対応した処理を実行
#main関数を再帰的に呼び出すのでpyfuncではなくmainに記述
def fileEvent(arg:list,loc:list):
    #何もないときはクリック
    if arg==None:
        pyautogui.click(loc[X],loc[Y])
    #クリックイベント
    elif arg[EVENT]==CLICK:
        loc=[x+y for (x,y) in zip(loc,arg[ARG1])]
        pyautogui.click(loc[X],loc[Y])
    #スワイプイベント
    elif arg[EVENT]==SWIPE:
        _n=None #未実装
    #再帰処理イベント
    elif arg[EVENT]==RECURE:
        flist=glob.glob(arg[ARG1]+FILE_TYPE)
        main([flist,arg[ARG2],arg[ARG3]])
    #終了イベント
    elif arg[EVENT]==EXIT:
        exit()

#受け取ったファイルリストとファイルイベントリストを元に
#イベントを実行し続ける
def main(arg:list):
    i:int=0
    while True:
        #画像認識チェック
        loc=pyautogui.locateCenterOnScreen(arg[FILES][i])
        if not(loc==None):
            time.sleep(arg[WAITTIME])
            #ファイルイベント実行
            fileEvent(getFileEvent(arg[FILES][i],arg[FILEEVENTS]),loc)
            i=sequentialCount(i,len(arg[FILES])-1)
        time.sleep(arg[WAITTIME])

flist=glob.glob(MAIN_PATH+FILE_TYPE)
main([flist,FILEEVENTS_MAIN,0.5])

前回に比べると一気に長くなりましたが殆どは定数の宣言ですね。

簡単な説明

pydef.py
    [".\\MVPlay\\03scroll.png",CLICK,[220,630],None,None]

この定義はパスを含め".\MVPlay\03scroll.png"と同じ名前のファイルが読み込まれた時、画像認識でマッチしたX座標とY座標にそれぞれ220,620を加算してクリックするという意味です。

main.py
#イベントに対応した処理を実行
#main関数を再帰的に呼び出すのでpyfuncではなくmainに記述
def fileEvent(arg:list,loc:list):
    #何もないときはクリック
    if arg==None:
        pyautogui.click(loc[X],loc[Y])
    #クリックイベント
    elif arg[EVENT]==CLICK:
        loc=[x+y for (x,y) in zip(loc,arg[ARG1])]
        pyautogui.click(loc[X],loc[Y])
    #スワイプイベント
    elif arg[EVENT]==SWIPE:
        _n=None #未実装
    #再帰処理イベント
    elif arg[EVENT]==RECURE:
        flist=glob.glob(arg[ARG1]+FILE_TYPE)
        main([flist,arg[ARG2],arg[ARG3]])
    #終了イベント
    elif arg[EVENT]==EXIT:
        exit()

ファイルに定義されたイベントは今回新たに追加されたfileEvent関数で処理されます。
CLICK以外のイベントは必要になるかもしれない程度なので今の所特に意味はないです。

総評

これでMVボタンを押す→再生ボタンを押す→MV再生が終わって曲リスト画面に戻ったら次の曲に移動するという一連の作業が自動化されました。
今回組んでて思ったのはlistが便利すぎるということに尽きます、話に聞いてもいまいちピンときてなかったですが触ってみると実感できますね、ファイルイベント定義してるところでコールバック関数呼び出しさせる設計も楽しいかもしれません。

最後に

曲リスト移動機能もついたので、大分自分の理想とする連続再生に近づいてきた感はありますが、未クリアの曲及びMVが未実装の曲の所で止まってしまうという問題は依然残っています。
次はこの問題点の解消を行っていきたいと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away