Lua」タグアーカイブ

mpv scripts

今日も mpv を Lua で弄る。

で、例によってディレクトリ内巡回機能なんですが。
筆者は再生終了で本体を終了しないように指定している。
再生中に「次のファイル」とすると普通に上手く切り替わるんだけど。
EOF 状態からだとファイルは切り替わるけどポーズされた状態で始まる。

GStreamer は EOS(End of Stream) という表現だったけど。
mpv では EOF(End of File) なんですね、同じ意味だしどうでもいいけど。

試しに途中でポーズして切り替えだと完全に同じだ。
つまり mpv の EOF は単にポーズされた状態。
もしポーズだったら解除する、というコードを追加すればいい。

mp.command('loadfile "file://'..directory..filename..'"')
-- これでもいい、true|false を yes|no の文字列で
--if mp.get_property('pause') == 'yes' then
if mp.get_property_bool('pause') then
    mp.set_property_bool('pause', false)
    -- これでもいい、true|false を yes|no の文字列で
    --mp.set_property('pause', 'no')
end
break

mpv の property アクセスは全部文字列。
UNIX 系を知っているなら macOS を含んでありがちだと解りますね。
コレを直接 Lua から使える BOOL 値で取り出せるのが _bool 付き関数。

ところで。
~/.config/mpv/scripts
にソースを放り込めば全部が起動時に読み込みされ適用されていくんだね。
これは機能ごとに分割したほうが色々と都合がいい。

そういえばアスペクト比変更もデフォルトでは割り付けされていない。
色々割り付けても筆者はキーを忘れるので Ctrl+2 でサイクルがいいな。
-1 を突っ込むとデフォルトになるので一周させるようにすれば完璧。
OSD(On Screen Document) で表示もあると良さげ。

-- ~/.config/mpv/scripts/mpv_aspect_rate.lua

aspect_num = 0
aspects = {'4:3', '16:9', '1:1'}

function on_change_aspectrate()
    aspect_num = aspect_num + 1
    if aspect_num > #aspects then
        aspect_num = 0
        mp.set_property('video-aspect', '-1')
        mp.osd_message('Aspect Rate @ Default')
    else
        mp.set_property('video-aspect', aspects[aspect_num])
        mp.osd_message('Aspect Rate @ '..aspects[aspect_num])
    end
end
mp.add_key_binding('Ctrl+2', 'aspectrate_func', on_change_aspectrate)

これを放り込んで、よし動いた。
グローバル変数はインスタンス毎に記憶してくれるようだ、助かる。
以降 mpv プログラミングはまとめたページを作るか。

いやープログラミングって面白いですね。
Lua は別に面白くないけど書いたら思った通りに動いてくれるのが面白い。
言語はただの道具で重要なのは完成品、実社会と同じ。

not =

Lua で凄い勘違いをしていた!
~= の演算子を bash の =~ と同じものだと思いこんでいた。
bash の != がコレなのね、何を今頃。

ちなみに。

#!/bin/sh

if [[ aaa.mp4 =~ \.(mov|mp4)$ ]]; then
    echo 動画ファイルです
fi

こんな感じで使います。
bash ですら複数拡張子のマッチを調べられるのに Lua ときたら…

いやまあ。
「Lua って != が無いのか、変わった言語だなぁ」
って思いこんで今まで not を使ってたよ。
それどころか。

#!/usr/bin/lua

if 1 ~= 2 then
    print('lua の ~= は bash の != と同じ意味です')
end

if not(nil) then
    print('nil は否です')
end

-- よく考えたら下記で良かった

--if not(extstr:match(ext) == nil) then
if extstr:match(ext) then

スゲェ無駄なコードを昨日まで書いていた。
もう少し勉強しなきゃとも思うけど。
mpv の拡張以外でこの言語を使うか疑問なんだよな。

Lua filename

前回 Lua スクリプトで mpv でのディレクトリ内巡回機能を作った。
まだ気に入っていない、拡張子 mp4 のファイルしか抜き出していない。
LUMIX で動画を撮影したものは mp4 だけど iPhone の動画は mov だ。

2022 年となった今ではこの二つだけでいいかもだけど他の形式も沢山ある。
Lua の正規表現を調べまくっているが複数の拡張子にマッチさせる手段が見つからない。
だからといって複数の拡張子全部の if 文を書くなんてまるで初心者だし。
後で簡単に書き加えなんかもできるようにしたいのでソレは絶対に避けたい。

しかたがない、別の方法でも考えよう。
配列に入れて if-in は、そんなの Python くらいしか出来ない。
Javascript の includes みたいなメソッドも無い、だめだ。

だったら文字列だ、ある文字列が長い文字列の中に含まれているかどうか。
おっとこれならできるみたいだぞ、よしまず拡張子を抜き出す手段を。

#!/usr/bin/lua

fullpath = '/home/testuser/動画/日本語 スペース.mp4'

dir = fullpath:match('.*/')
print(dir)
--> /home/testuser/動画/

file = fullpath:match('.*/(.*)')
print(file)
--> 日本語 スペース.mp4'

ext = fullpath:match('.*%.(.*)')
print(ext)
--> mp4

none = fullpath:match('.*%](.*)')
print(none)
--> nil

拡張子やファイル名を抜き出すにはコレでいいようだ。
どうでもいいけど Gedit では Lua でもシバンには色が付くんだね。

lua_gedit

Lua の # はコメントじゃないのに、Python の len() 相当です。

#!/usr/bin/lua

extstr = 'mp4,m4v,mov'

bool = extstr:match('mov')
print(bool)
--> mov

bool = extstr:match('wmv')
print(bool)
--> nil

とにかく存在しないなら nil になる、コレを利用しよう。

extstr = 'mp4,m4v,mov'

function on_nextfile()
    -- 略
    for filename in pfile:lines() do
        -- 拡張子を抜きだして小文字化して
        ext = filename:match('.*%.(.*)'):lower()
        -- 含まれていなければ nil になる
        if not(extstr:match(ext) == nil) then

ということで書き換え、上手くいったので前回の投稿も書き換えしました。

mpv settings

Fedora 35 にしてから Celluloid がどうにも調子が悪い。
ブツブツとブラックアウトが入る、筆者自作の奴はもっと調子が悪いけど。

原因が解らない、mpv ライブラリが原因かな?
と思い確認のため素の mpv を入れてみた、dnf で普通に入れられる。
コチラはなんともない、てか mpv ってこんな感じだったっけ?
いや以前試しに使ってみたことはあるんだけど、もう何年も前だし。

今の筆者はコレで充分なんだけど、ということで乗り換えすることにした。
で、カスタムする方法を検索していたんですけど。

mpv – ArchWiki

日本語ページでは上記以外は情報が古過ぎで役に立たないな。
とにかく Linux でもハードウエア・アクセラレーションが使えると今頃知った。
あれ?と思ったけど筆者のその手の知識が古すぎるんだな。
それはそうと、Fedora では別途2つのライブラリを追加する必要がある。

Hardware decoding on Linux ? mpv-player/mpv Wiki ? GitHub

# Fedora dnf command
sudo dnf install libva-intel-driver
sudo dnf install libva-intel-hybrid-driver

Intel HD graphics の場合です。
AMD のグラフィックって元 ATI だし Linux への対応なんてお察しで。

準備はこれだけ、後は好みでカスタムしていくんですが拘りが二つ。
Esc はフルスクリーン解除、フルスクリーンでなければウインドウを閉じる。
ようするに Eye of GNOME の動作に合わせたい、筆者自作の奴もそうしていますし。
それとやはりディレクトリ内巡回機能が、プレイリスト化するのメンドイもん。
Ctrl+Down Ctrl+UP が標準では空いているのでココに割り付けしたい。

mpv.io

Lua や Javascript でなんとかなるっぽい。
こいつの js で ls する方法が解らないので Lua を久々に。
Lua の正規表現ってショボいな。
Javascript の /\.(mp4|m4v|mov)$/i を同様に定義できないんだが。
とりあえず *.mp4 だけでやってみた関数群。

ファイル名は何でもいい、場所は一行目に。
2022.01.12 複数の拡張子対応に書き換え、extstr 変数で指定

-- ~/.config/mpv/scripts/mpv_func.lua

extstr = 'mp4,m4v,mov'

-- Esc 時にフルスクリーンなら解除、でなければ終了
function on_escape()
    if mp.get_property_bool('fullscreen') then
        mp.set_property('fullscreen', 'no')
    else
        mp.command('quit')
    end
end
mp.add_key_binding('Esc', 'esc_func', on_escape)

-- Ctrl+DOWN でディレクトリ内の次ファイルを再生
function on_nextfile()
    local ex = false
    local fn = mp.get_property('filename')
    local directory = mp.get_property('path'):match('.*/')
    local pfile = io.popen('ls  "'..directory..'"')
    for filename in pfile:lines() do
        ext = filename:match('.*%.(.*)'):lower()
        if not(extstr:match(ext) == nil) then
            if ex then
                mp.command('loadfile "file://'..directory..filename..'"')
                break
            end
            ex = filename == fn
        end
    end
    pfile:close()
end
mp.add_key_binding('Ctrl+DOWN', 'nextfile_func', on_nextfile)

-- Ctrl+UP でディレクトリ内の手前ファイルを再生
function on_prevfile()
    local prevfn = ''
    local fn = mp.get_property('filename')
    local directory = mp.get_property('path'):match('.*/')
    local pfile = io.popen('ls  "'..directory..'"')
    for filename in pfile:lines() do
        ext = filename:match('.*%.(.*)'):lower()
        if not(extstr:match(ext) == nil) then
            if filename == fn then
                if not(prevfn == '') then
                    mp.command('loadfile "file://'..directory..prevfn..'"')
                end
                break
            end
            prevfn = filename
        end
    end
    pfile:close()
end
mp.add_key_binding('Ctrl+UP', 'prevfile_func', on_prevfile)

ハードウエア・アクセラレーション

# ~/.config/mpv/mpv.conf

# ハードウエア・アクセラレーション
profile=gpu-hq
hwdec=vaapi
tscale=oversample
correct-pts=yes

# 下記を指定すると筆者の環境 (i5-6500) ではコマ落ちする。
#scale=ewa_lanczossharp
#cscale=ewa_lanczossharp
#video-sync=display-resample

# 再生終了で本体を終了しない
keep-open=yes

ショートカット、とにかく EoG に合わせる

# ~/.config/mpv/input.conf

# GtkApplication ではないので Ctrl+Q で全体終了はできないけど
Ctrl+q quit
Ctrl+w quit

# GNOME アプリのフルスクリーンは F11 です
F11 cycle fullscreen

# 小さい動画は Ctrl+1 で FullHD にリサイズ
Ctrl+1 set autofit 1920x1080

# 回転、マイナスにはできないようなので
Ctrl+r add video-rotate 90
Ctrl+Shift+r add video-rotate -90
Ctrl+e add video-rotate 270
Ctrl+Shift+e add video-rotate -270

オンスクリーンコントローラを小さく

# ~/.config/mpv/script-opts/osc.conf

# 動画に合わせた OSC リサイズを無効に
vidscale=no

# OSC のサイズを少し小さくしてシークバー領域を増やす
scalewindowed=0.75
scalefullscreen=0.75

で。

vaapi

vaapi が適用され動作も筆者の好みな環境ができあがりました。
もう筆者はプレイヤーを自作しなくていいな、そろそろ公開終了するか。
これからはスクリプトで拡張の時代ですよ。

いや、LUMIX らしく動画もやろうかなとも思ったんだけど。
手持ちじゃユラユラしちゃって、コレこそ三脚無しじゃ不可能でした。