Lua」タグアーカイブ

MPV AspectRate Change (2024)

いつのまにか MPV にてアスペクト比変更ができなくなっていた。
いや Shift+a での変更は可能、自作した拡張 Lua スクリプトが動かない。

How to add 21:9 Aspect ratio option in MPV Android? : r/mpv

色々探して上記を見つける。
video-aspect-override という property があるのね。

--mp.set_property('video-aspect', aspects[aspect_num])
mp.set_property('video-aspect-override', aspects[aspect_num])

これで動いた、思っていたより簡単でよかった。
Fedora の MPV は更新されていないし ffmpeg 側の仕様変更かな?
なので環境によって変わると思う、Fedora 40 な人は書き換え必須です。

せっかくなので Shift 追加で逆順変更機能も付けてみよう。

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

-- Shift+a でアスペクト比は変更できますけど
-- スマホの縦動画用が足りないので独自に作ってみました

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

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

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

こんな感じになった。

しかし Kate は今だに使い辛いなぁ。
コードやブログネタを書いて余計な補完機能を見つけて無効化するばかり。
macOS で Sublime Text は Gedit でやっていたことを再現できたんだけど。
Kate は無理っぽい、でも Gedit は死亡したも同然だし代わりも見つからない。

mpv: rotate

mpv をスクリプトで拡張をまとめてページを作ろうとして、欲が出た。
動画の回転を Eye of GNOME や Totem に合わせたい。
具体的には Ctrl+R で 90° ずつ時計回り、Shift 追加で逆回り。

今まで Ctrl+E を逆回りに割り当てていたけど、やはりおかしい。
それに割り当てする値は 0-359 以内にしないとエラーになる。
input.conf ではどうにもならない、Lua スクリプトを書く。

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

-- input.conf に 'Ctrl+r add video-rotate 90' でもいいけど
-- 0-359 以内にしないとエラーなのとキーを Eye of GNOME に合わせたかったので

function on_rotate_right()
    angle = mp.get_property('options/video-rotate')
    num = tonumber(angle) + 90
    if num > 270 then
        num = 0
    end
    mp.osd_message('angle:'..tostring(num)..'°')
    mp.set_property_number('options/video-rotate', num)
end

function on_rotate_left()
    angle = mp.get_property('options/video-rotate')
    num = tonumber(angle) - 90
    if num < 0 then
        num = 270
    end
    mp.osd_message('angle:'..tostring(num)..'°')
    mp.set_property_number('options/video-rotate', num)
end

mp.add_key_binding('Ctrl+r', 'rotate_right', on_rotate_right)
mp.add_key_binding('Ctrl+Shift+r', 'rotate_left', on_rotate_left)

osd も入れて。

よし問題なく動くぞ。
macOS な人は逆回転を command+L にすれば Preview.app と同じになる。

ついでに、time-pos プロパティをゼロにすれば先頭に巻き戻しできるけど。
最後まで再生してポーズ状態からだとポーズのまま、即再生させたいのよ筆者は。

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

-- Home キーで先頭に巻き戻して再生する
-- 最後まで再生しポーズ状態になっていても即再生できるように

function on_go_home()
    mp.set_property_number('time-pos', 0)
    if mp.get_property_bool('pause') then
        mp.set_property_bool('pause', false)
    end
end
mp.add_key_binding('Home', 'go_home_func', on_go_home)

できた。

いやいや input.conf がスッカラカンに。
自分で拡張できるアプリって面白いよね。

mpv: Ctrl+q @ Close all MPV Windows

Fedora で mpv を使って困ること。
Ctrl+q で複数起動したすべての mpv を終了できないこと。

だって GNOME のアプリは全部そうなっているんだもの。
そういえば Chrome が Fedora では終了できないな、狐はできるのに。
コレは GNOME アプリ同様 Ctrl+w 連続押しで代用できるのでまあよし。

macOS では command+q ですね、サードパーティすら全部。
そりゃ macOS はウインドウを全部閉じても終了できないんだから必須機能。
唯一 Finder だけが不可、ファイルマネージャは常に起動しているし。

でも Nautilus は Ctrl+q で全部のウインドウを閉じてくれる動作をする。
そんなこんなで、凄く気になるんですよ。

で、よく考えたら UNIX には killall コマンドがあった。
Linux ではコマンドと GUI の区別が無いんだから使えるかも。
ということで Lua スクリプト。

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

-- Ctrl+q @ Close all MPV Windows.
function on_close_all()
    os.execute('killall mpv')
end
mp.add_key_binding('Ctrl+q', 'close_all_func', on_close_all)

これをスクリプトディレクトリに突っ込んで。
おぉ自分を含めて全部終了してくれる、やったね。
macOS では GUI は区別されているから無理だと思う。
統一されたキーボード操作が無い某 OS はどうでもいいね。

ついでに、最近の mpv osc 設定。
シークバーは QuickTime のようにフローティングもできると知った。

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

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

# 薄くする
boxalpha=180

# 常にトータル時間
timetotal=yes

# タイトルはファイル名 -- タイトル名
title=${filename} -- ${media-title}

# シークバーのみに、弄る時に枠外になるのを防げる
layout=slimbox
seekbarstyle=diamond
valign=0.95

kogera

てかシークバーだけにできるんだ、こりゃいいわ。
だって osc ってシークバーしか使わないよねみんな。

kogera

QuickTime も再生ボタンとか消せないかなぁって。
macOS では動画はほとんど見ないので QuickTime のままです。
ちなみに QuickTime だけで動画の切り貼りやリサイズ保存ができる。
筆者の編集範囲ならコイツだけで完了するので重宝していたりします。

mpv @ Next File (Nautilus Sort)

しつこいようだけど mpv で次のファイルを再生させるスクリプト。
順番が Nautilus と同じでないのでイマイチ不便だなって。

だったらコレも作ってしまえ!
Gjs なり PyGObject なりでソートさせて出力するコマンドを。
mpv の拡張スクリプトでは無理なのでコマンドを自作する。
それを Lua で呼び出せばなんとかなるはず。

ついでに、いちいち拡張子を指定するのも面倒臭い。
てか Lua がショボいなら自作コマンドのほうで正規表現を使えばいい。
で、GNOME では動画ファイルの ContentType は以下のようになっている。

video/mp4
video/quicktime
video/x-matroska

ContentType なら先頭の video/ だけで動画ファイルを見分けできる。
ということでこんなスクリプトを書いてみた。

#!/usr/bin/gjs

if (ARGV.length == 0) {
    print('usage: nautilus_ls {DIRNAME}');
} else {
    const GLib = imports.gi.GLib;
    const Gio = imports.gi.Gio;
    const re = /^video\//;

    let files = [];
    let d = Gio.file_new_for_path(ARGV[0]);
    let ls = d.enumerate_children('standard::content-type', 0, null);
    for (;;) {
        let info = ls.next_file(null);
        if (info == null)
            break;
        let t = info.get_content_type();
        if (re.test(t))
            files.push(info.get_name());
    }
    files.sort((s1, s2)=> {
        let cmpstr1 = GLib.utf8_collate_key_for_filename(s1, -1);
        let cmpstr2 = GLib.utf8_collate_key_for_filename(s2, -1);
        if (cmpstr1 < cmpstr2)
            return -1;
        return 1;
    });
    print(files.join('\n'));
}

// ex: ft=js

Gjs での例。
nautilus_ls という拡張子無しファイル名でパスの通った場所に保存。
実行パーミッション追加でコマンドの出来上がり。
このコマンドを Lua で呼び出しする。

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

local utils = require 'mp.utils'

-- Ctrl+DOWN @ Next File Play
function on_nextfile()
    local hit = false
    local directory, fn = utils.split_path(mp.get_property('path'))
    if directory == '.' then
        directory = utils.getcwd()
    end
    local pfile = io.popen('nautilus_ls  "'..directory..'"')
    for filename in pfile:lines() do
        if hit then
            mp.commandv('loadfile', utils.join_path(directory, filename))
            if mp.get_property_bool('pause') then
                mp.set_property_bool('pause', false)
            end
            break
        end
        hit = filename == fn
    end
    pfile:close()
end
mp.add_key_binding('Ctrl+DOWN', 'nextfile_func', on_nextfile)

-- Ctrl+UP Previous File Play
function on_prevfile()
    local prevfn = ''
    local directory, fn = utils.split_path(mp.get_property('path'))
    if directory == '.' then
        directory = utils.getcwd()
    end
    local pfile = io.popen('nautilus_ls  "'..directory..'"')
    for filename in pfile:lines() do
        if filename == fn and prevfn ~= '' then
            mp.commandv('loadfile', utils.join_path(directory, prevfn))
            if mp.get_property_bool('pause') then
                mp.set_property_bool('pause', false)
            end
            break
        end
        prevfn = filename
    end
    pfile:close()
end
mp.add_key_binding('Ctrl+UP', 'prevfile_func', on_prevfile)

イケた!
GNOME 限定です、他の環境の人は参考程度に。

mpv @ Lua to Javascript

mpv を Lua で拡張するのが楽しい皆様。
こんなトコを見つけました。

GitHub – samhippo/mpv-scripts

参考になります、いやコピペでそのまま使ってもいいんだけど。
Windows 限定のコードが所々あるので macOS や Fedora の人は注意です。

そういえばこの人は複数拡張子のマッチをどうやっているんだろう?

mpv-scripts/next-file.lua at master ? samhippo/mpv-scripts ? GitHub

拡張子文字列で連想配列を作り値を全部 true に。

lua_nil

存在しなければエラーではなく nil になる、なるほど。
酷い手段だけど Lua 自体が色々とショボいからしかたがないか。

いやまて、この方法でディレクトリ内を列挙できるんだよな。
ls コマンドが不要なら正規表現が強力な Javascript を使うという手が。
とりあえず mp.utils を Javascript ではどう呼び出すか試す。

// ~/.config/mpv/scripts/test.js

function on_test() {
    //let dir = mp.utils.split_path(mp.get_property('path')); // ES5...
    var dir = mp.utils.split_path(mp.get_property('path'));
    mp.osd_message('Playng File: ' + dir[1]);
}
mp.add_key_binding('Ctrl+3', 'test_func', on_test);

なんだ、ドットで普通に使えるヤン。
しかし let 宣言でエラー、まさか今更 ECMAScript 5…

mpv.io

mpv.io にも書いていた、for-of とかも当然使えないな。
ES5 でも正規表現は同じはずだ、使ってみる。
以前書いたディレクトリ内で次のファイルを js で丸ごと書き換え。

// ~/.config/mpv/scripts/next_prev.js

var re = /\.(mov|m4v|mp4)$/i;

// Ctrl+DOWN でディレクトリ内の次ファイルを再生
function on_nextfile() {
    var dir = mp.utils.split_path(mp.get_property('path'));
    // カレントディレクトリだとドットになるので
    if (dir[0] == '.') dir[0] = mp.utils.getcwd();
    // ls
    var ls = mp.utils.readdir(dir[0], 'files');
    ls.sort();
    if (mp.last_error() == '') {
        // for-of が使いたい...
        var len = ls.length;
        var ex = false;
        for (var i=0; i<len; i++) {
            var f = ls[i];
            if (re.test(f) && ex) {
                mp.commandv('loadfile', mp.utils.join_path(dir[0], f));
                if (mp.get_property_bool('pause'))
                    mp.set_property_bool('pause', false);
                break;
            }
            ex = f == dir[1];
        }
    }
}
mp.add_key_binding('Ctrl+DOWN', 'nextfile_func', on_nextfile);

// Ctrl+UP でディレクトリ内の手前ファイルを再生
function on_prevfile() {
    var prevfn = '';
    var dir = mp.utils.split_path(mp.get_property('path'));
    if (dir[0] == '.') dir[0] = mp.utils.getcwd();
    var ls = mp.utils.readdir(dir[0], 'files');
    ls.sort();
    if (mp.last_error() == '') {
        var len = ls.length;
        var ex = false;
        for (var i=0; i<len; i++) {
            var f = ls[i];
            if (re.test(f)) {
                if (dir[1] == f && prevfn != '') {
                    mp.commandv('loadfile', mp.utils.join_path(dir[0], prevfn));
                    if (mp.get_property_bool('pause'))
                        mp.set_property_bool('pause', false);
                    break;
                }
                prevfn = f;
            }
        }
    }
}
mp.add_key_binding('Ctrl+UP', 'prevfile_func', on_prevfile);

動くジャン。
ただ ls と違ってソートしないとよくワカラン順番になるみたい。

loadfile は半角スペース付きでもダブルクォートで囲む必要は無かったのね。
というか URI にする必要すら無かった、とほほ。

とにかくコレで完璧な拡張子判別ができるようになった。
慣れた言語はやっぱり楽だね、言語仕様を調べる必要が無いし。
自由に改造して使ってください、Windows でも多分動くと思う。