XScreenSaverと動画視聴時のスクリーンセーバー抑制

こちらのフォーラムに回答したのですが,色々余計なことも書きたかったのでここに書いておきます.

XScreenSaverの自分の大体の設定,動画視聴時のスクリーンセーバー抑制についてです.ここではXScreenSaverの説明ですが,GnomeやKDE,Cinnamonなどでもコマンドを置き換えることでほぼ同じように使えるはずです.

Note
例えばGnome ScreenSaverの場合 xscreensaver-commandgnome-screensaver-command に置き換える

2021-03-25追記)
XScreenSaver FAQ を見ると,XScreenSaver 5.45以降はFirefox, Chrome, Chromium, MPV, VLCでの動画視聴時にスクリーンセーバーが抑制されるようになっているようです.確認すると,xprintidleはカウントされますがスクリーンセーバーは抑制されるといった動作になっているようです.

XScreenSaverの設定

$ sudo apt install xscreensaver

xscreensaver パッケージを導入します.

$ dpkg-query -W xscreensaver*
xscreensaver    5.45+dfsg1-1
xscreensaver-data       5.45+dfsg1-1
xscreensaver-data-extra 5.45+dfsg1-1
xscreensaver-gl 5.45+dfsg1-1
xscreensaver-gl-extra   5.45+dfsg1-1
xscreensaver-screensaver-bsod   5.45+dfsg1-1
xscreensaver-screensaver-dizzy  0.3-3.1

いろいろなスクリーンセーバーを使いたい場合その他のパッケージも導入します.

設定は xscreensaver-demo で行えます.

xscreensaver-demo

xscreensaver setting

私は,いくつかのスクリーンセーバーを有効にして,Modeを Random Screen Saver にして選択したスクリーンセーバーがランダムに起動するようにしています.

その他スクリーンセーバー起動時にロックするようにしています.離席時に他の人が触りにくくなります.

Blank After
指定した時間経過後スクリーンセーバー起動
Lick Screen After
スクリーンセーバー起動後指定時間でロックする(スクリーンセーバー解除時にパスワードが必要)

xscreensaver-command でスクリーンセーバー制御

xscreensaver-command というコマンドで制御が出来ます.私がよく使うオプションはこのあたりです.

-activate
スクリーンセーバーを有効にします
-deactivate
スクリーンセーバーを解除します
-lock
画面をロックします

1文字の省略形のオプションもありますが,manやhelpには載っていないので使わないほうがいいかもしれません.
私はこのコマンドで離席時画面をロックするためにキーボードショートカットに登録したり,以前は BlueProximity というソフトウェアでBluetoothデバイスを身につけてそれを持ったまま離席してある程度離れると画面をロックするというのに使っていました.(最近のDebian ではなくなっていたり,今使っているスマートフォンは少電力機能のせいかすぐロックされてしまうようになって今は使っていません.)

awesome wmでキーボード・ショートカット( Alt+l )でスクリーンロックする例.
    -- lock screen
    awful.key({ "Mod1"  }, "l", function () awful.util.spawn( "xscreensaver-command -lock",false) end),

xprintidleを見ながらスクリーンセーバー起動確認

スクリーンセーバーの設定を行って正しく起動するかを確認するとき xprintidle コマンドが便利です.

man xprintidle
       xprintidle is a utility that queries the X server for the user's idle time and prints it to stdout (in milliseconds).

Xサーバーのアイドル時間を表示してくれるコマンドです.単位はミリ秒です.

$ watch xprintidle

watch コマンドなどで定期的に呼ぶようにしてスクリーンセーバーの起動を待つとわかりやすいです.

mpvでスクリーンセーバー抑制

man mpv
       --stop-screensaver, --no-stop-screensaver
              Turns off the screensaver (or screen blanker and similar mechanisms) at startup and turns it on again on exit  (default:  yes).
              The screensaver is always re-enabled when the player is paused.

              This  is not supported on all video outputs or platforms. Sometimes it is implemented, but does not work (especially with Linux
              "desktops").

mpvにはスクリーンセーバー抑制オプションがありました.

$ echo 'alias mpv="mpv --stop-screensaver"' >> ~/.bashrc
$ source ~/.bashrc
$ alias | grep mpv
alias mpv='mpv --stop-screensaver'

alias や

$ cp /usr/share/applications/mpv.desktop ~/.local/share/applications/
$ vi ~/.local/share/applications/mpv.desktop
$ diff -u1 /usr/share/applications/mpv.desktop ~/.local/share/applications/mpv.desktop
--- /usr/share/applications/mpv.desktop 2020-08-13 05:52:09.000000000 +0900
+++ /home/matoken/.local/share/applications/mpv.desktop 2021-03-24 22:15:59.037232611 +0900
@@ -31,3 +31,3 @@
 TryExec=mpv
-Exec=mpv --player-operation-mode=pseudo-gui -- %U
+Exec=mpv --stop-screensaver --player-operation-mode=pseudo-gui -- %U
 Terminal=false

デスクトップファイルに設定しておくと良さそうです.

mplayerでスクリーンセーバー抑制

man mplayer
       -heartbeat-cmd
              Command that is executed every 30 seconds during playback via system() - i.e. using the shell.

              NOTE:  MPlayer  uses this command without any checking, it is your responsibility to ensure it does not cause security problems
              (e.g. make sure to use full paths if "." is in your path like on Windows).  It also only works when  playing  video  (i.e.  not
              with -novideo but works with -vo null).

              This can be "misused" to disable screensavers that do not support the proper X API (also see -stop-xscreensaver).  If you think
              this is too complicated, ask the author of the screensaver program to support the proper X APIs.

              EXAMPLE for xscreensaver: mplayer -heartbeat-cmd "xscreensaver-command -deactivate" file

              EXAMPLE for GNOME screensaver: mplayer -heartbeat-cmd "gnome-screensaver-command -p" file

mplayerには -heartbeat-cmd というオプションがあります.mpvと同じようにaliasやデスクトップファイルを編集しておくと便利です.

lightsOnスクリプトでスクリーンセーバー抑制

mpvやmplayerでは抑制できましたが,ウェブブラウザ等で動画閲覧時に抑制できません.そういうときに便利なのが lightsOn です.
各種動画プレイヤーや,ウェブブラウザでFlash/HTML5ビデオ再生時にスクリーンセーバーを抑制してくれます.これを使うと上のmpv/mplayerの設定も不要になります.

$ wget https://raw.githubusercontent.com/kodx/lightsOn/master/lightsOn.sh
$ chmod u+x ./lightsOn.sh
$ ./lightsOn.sh

とりあえず実行すればokです.

しかし手元の環境では xprop: unable to open display ':0.0' というメッセージで動作しませんでした.
DISPLAY番号が 0 で固定になっているせいのようです.

diff --git a/lightsOn.sh b/lightsOn.sh
index 6b5be4b..bdab249 100755
--- a/lightsOn.sh
+++ b/lightsOn.sh
@@ -162,7 +162,7 @@ checkFullscreen()
     for display in $displays
     do
         #get id of active window and clean output
-        activ_win_id=$(DISPLAY=:0.${display} xprop -root _NET_CLIENT_LIST_STACKING | sed 's/.*\, //') #previously used _NET_ACTIVE_WINDOW, but it didn't work with some flash players (eg. Twitch.tv) in firefox. Using sed because id lengths can vary.
+        activ_win_id=$(DISPLAY=${DISPLAY}.${display} xprop -root _NET_CLIENT_LIST_STACKING | sed 's/.*\, //') #previously used _NET_ACTIVE_WINDOW, but it didn't work with some flash players (eg. Twitch.tv) in firefox. Using sed because id lengths can vary.

         # Skip invalid window ids (commented as I could not reproduce a case
         # where invalid id was returned, plus if id invalid
@@ -173,8 +173,8 @@ checkFullscreen()

         # Check if Active Window (the foremost window) is in a fullscreen state
         if [[ -n $activ_win_id ]]; then
-            isActivWinFullscreen=$(DISPLAY=:0.${display} xprop -id $activ_win_id | grep _NET_WM_STATE_FULLSCREEN)
-            isActivWinAbove=$(DISPLAY=:0.${display} xprop -id $activ_win_id | grep _NET_WM_STATE_ABOVE)
+            isActivWinFullscreen=$(DISPLAY=${DISPLAY}.${display} xprop -id $activ_win_id | grep _NET_WM_STATE_FULLSCREEN)
+            isActivWinAbove=$(DISPLAY=${DISPLAY}.${display} xprop -id $activ_win_id | grep _NET_WM_STATE_ABOVE)
             log "checkFullscreen(): Display: $display isFullScreen: \"$isActivWinFullscreen\""
             log "checkFullscreen(): Display: $display isAbove: \"$isActivWinAbove\""
             if [[ "$isActivWinFullscreen" = *NET_WM_STATE_FULLSCREEN* || "$isActivWinAbove" = *NET_WM_STATE_ABOVE* ]];then

少し書き換えて使っています.

これを自動起動するようにしておくと動画視聴時に抑制されます.

私はNetworkManagerのScriptで自宅のネットワークの場合起動するようにしています.その他のネットワークでは起動しない → スクリーンセーバーが抑制されない.

環境

$ dpkg-query -W xscreensaver* mpv mplayer xprintidle
mplayer 2:1.4+ds1-1
mpv     0.32.0-2+b1
xprintidle      0.2.4-1
xscreensaver    5.45+dfsg1-1
xscreensaver-data       5.45+dfsg1-1
xscreensaver-data-extra 5.45+dfsg1-1
xscreensaver-gl 5.45+dfsg1-1
xscreensaver-gl-extra   5.45+dfsg1-1
xscreensaver-screensaver-bsod   5.45+dfsg1-1
xscreensaver-screensaver-dizzy  0.3-3.1
$ lsb_release -dr
Description:    Debian GNU/Linux bullseye/sid
Release:        unstable
$ uname -m
x86_64

Debian sidでLinux Kernel(5.11)をbuildするメモ

Linux kernelの新機能を試したくてディストリビューションパッケージより新しいものを使いたいことがあります.
毎回注ぎ足しつぎ足しで設定しているので実際試すと足りないパッケージ等あると思いますが大雑把に最近のkernelのbuild手順をメモしておきます.

関連パッケージの導入

$ sudo apt install build-essential fakeroot gpg2
$ sudo apt build-dep linux

ソースの入手と署名の確認

$ wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.11.tar.xz https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.11.tar.sign
$ unxz ./linux-5.11.tar.xz
$ gpg --verify ./linux-5.11.tar.sign
gpg: assuming signed data in './linux-5.11.tar'
gpg: Signature made Mon 15 Feb 2021 06:11:32 PM JST
gpg:                using RSA key 647F28654894E3BD457199BE38DBBDC86092693E
gpg: Good signature from "Greg Kroah-Hartman <gregkh@linuxfoundation.org>" [unknown]
gpg:                 aka "Greg Kroah-Hartman (Linux kernel stable release signing key) <greg@kroah.com>" [undefined]
gpg:                 aka "Greg Kroah-Hartman <gregkh@kernel.org>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 647F 2865 4894 E3BD 4571  99BE 38DB BDC8 6092 693E
$ tar tvf ./linux-5.11.tar | lv
$ tar xf ./linux-5.11.tar
$ cd linux-5.11

sourceは kernel.org からアーカイブを入手しました.余裕があったらgitリポジトリのほうが便利だと思います.

署名は以下から確認します.

署名はxzではなくtarに対してのものなので一旦.xzから展開した.tarで確認します.
署名チェックがOKだったら展開します.

configの作成

$ cp /boot/config-`uname -r` ./.config
$ make oldconfig

kernelの .config ファイルを現在のKernelの .config を元に作成します.
make oldconfig で差分の変更を対話形式で聞いてくるので答えていきます.すべてデフォルトにする場合は olddefconfig を使います.

$ make xconfig

カスタマイズが必要な場合は make menuconfig, nconfig 等でカスタマイズします.
GUIの場合xconfig(QT base)/gconfig(GTK+ base)などが便利だと思います.

.config が更新されます.

$ make testconfig

設定後一応テストしておきます.

セキュアブートのためのDebian UEFI証明書をコピー(セキュアブートを使わない場合はスキップ)

$ tar xf ../linux_5.10.9-1.debian.tar.xz debian/certs/

既存のDebian kernel source( apt source linux で入手可能)からコピーしてきます.(他に正攻法がある気がする)

2021-04-28 追記)
Debian pkgのLinux source から貰ってこなくても .configCONFIG_SYSTEM_TRUSTED_KEYS""にすることでエラーを回避できるようです.

@@ -9373,7 +9375,7 @@
#
CONFIG_MODULE_SIG_KEY=""
CONFIG_SYSTEM_TRUSTED_KEYRING=y
-CONFIG_SYSTEM_TRUSTED_KEYS="debian/certs/debian-uefi-certs.pem"
+CONFIG_SYSTEM_TRUSTED_KEYS=""
# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set
CONFIG_SECONDARY_TRUSTED_KEYRING=y
CONFIG_SYSTEM_BLACKLIST_KEYRING=y

Linux 5.12.0 でセキュアブート出来るのを確認しました.

build

$ time make -j`nproc` bindeb-pkg
  :
  dpkg-deb: building package 'linux-libc-dev' in '../linux-libc-dev_5.11.0-1_amd64.deb'.
dpkg-deb: building package 'linux-image-5.11.0' in '../linux-image-5.11.0_5.11.0-1_amd64.deb'.
dpkg-deb: building package 'linux-image-5.11.0-dbg' in '../linux-image-5.11.0-dbg_5.11.0-1_amd64.deb'.
 dpkg-genbuildinfo --build=binary
 dpkg-genchanges --build=binary >../linux-5.11.0_5.11.0-1_amd64.changes
dpkg-genchanges: info: binary-only upload (no source code included)
 dpkg-source --after-build .
dpkg-buildpackage: info: binary-only upload (no source included)
$ ls -1s ../linux*.deb
  7932 ../linux-headers-5.11.0_5.11.0-1_amd64.deb
728724 ../linux-image-5.11.0-dbg_5.11.0-1_amd64.deb
 52136 ../linux-image-5.11.0_5.11.0-1_amd64.deb
  1124 ../linux-libc-dev_5.11.0-1_amd64.deb

buildして成功するとパッケージが生成されます.

CPU i5-3320M/RAM 16GB/SATA SSDの環境で200分程かかりました.別の作業をしながらだとさらに時間が伸びます.

kernelパッケージを導入

$ sudo apt install ../linux-image-5.11.0_5.11.0-1_amd64.deb ../linux-libc-dev_5.11.0-1_amd64.deb ../linux-headers-5
.11.0_5.11.0-1_amd64.deb

出来上がったkernelパッケージを導入します.

古いkernelパッケージの削除

古い使わなくなったKernelパッケージはディスクを消費するので(特に /boot )削除しましょう

$ dpkg -l linux-image* | grep ^ii
ii  linux-image-5.10.0-4-amd64          5.10.19-1          amd64        Linux 5.10 for 64-bit PCs (signed)
ii  linux-image-5.11.7                  5.11.7-2           amd64        Linux kernel, version 5.11.7
ii  linux-image-5.11.8+                 5.11.8+-3          amd64        Linux kernel, version 5.11.8+
$ sudo apt purge linux-image-5.11.7

インストールされているパッケージを確認して古いものを削除します.

Machine Owner Keyで署名する(セキュアブートを使わない場合はスキップ)

前もってMOK(Machine Owner Key)の用意をして設定しておきます.MOKの作成についてはこちらを.

$ sudo sbsign --key ~/MOK.priv --cert ~/MOK.pem /boot/vmlinuz-5.11.0 --output vmlinuz-5.11.0
$ sudo mv ./vmlinuz-5.11.0 /boot/vmlinuz-5.11.0

Kernelに署名します.
ここでは作成したMOKの鍵( ~/MOK.priv )と証明書( ~/MOK.pem )を使い, /boot/vmlinuz-5.11.0 に署名して差し替えています.

$ find /lib/modules/5.11.0/updates/dkms/ -type f -print0 | xargs -0 -n1 sudo ./scripts/sign-file sha256 ~/MOK.priv ~/MOK.der

DKIMで作られたモジュールにも署名します.

追記 20210830)

/etc/dkms/sign_helper.sh というファイルがありました.

/etc/dkms/sign_helper.sh
#!/bin/sh
/lib/modules/"$1"/build/scripts/sign-file sha512 /root/mok.priv /root/mok.der "$2"

MOKのファイルを /root/mok/priv, /root/mok.der, /root/mok.pem としておくと dkms 実行時に自動的に署名してくれるようです.kernel install時だけでなく dkms 更新時などにも自動実行してくれるので署名し忘れが無くなって助かります.

changelog を見ると dkms 2.8.3-3 から入ったようです.

/usr/share/doc/dkms/changelog.Debian.gz
dkms (2.8.3-3) unstable; urgency=medium

  * dynamically generate breaks for shim-signed in Ubuntu and Derivates

 -- Gianfranco Costamagna <locutusofborg@debian.org>  Wed, 29 Jul 2020 10:30:50 +0200

再起動して反映

うまく行けば新しいKernelで起動できます.
うまく行かない場合は古いKernelで起動して設定し直しましょう.

patch

kernel.orgにはパッチが2種類あります.n.y.0からの累積パッチとすぐ前のバーションからのインクリメンタルパッチがあります.

$ sudo apt install patch

patch パッケージが必要なので導入しておきます.

累積patch

上ではKernel 5.11.0をbuildしました.Kernel 5.11.7を適用します.

$ wget https://cdn.kernel.org/pub/linux/kernel/v5.x/patch-5.11.8.xz

間が空いているので累積パッチを入手します.

$ cd linux-5.11
$ xzcat ../patch-5.11.8.xz | patch -p1

sourceディレクトリに移動してパッチを適用します.

あとは上の手順と同じです.

インクリメンタルpatch

次に 5.11.7 から 5.11.8 のように1つだけアップデートしたいときのインクリメンタルパッチの手順です.

$ wget https://cdn.kernel.org/pub/linux/kernel/v5.x/incr/patch-5.11.7-8.xz

インクリメンタルパッチを入手します.

$ cd linux-5.11
$ xzcat ../patch-5.11.7-8.xz | patch -p1

sourceディレクトリに移動してパッチを適用します.

あとは上の手順と同じです.

環境

$ sudo lshw -c system -sanitize | head
computer
    description: Notebook
    product: 23533KJ (LENOVO_MT_2353)
    vendor: LENOVO
    version: ThinkPad T430s
    serial: [REMOVED]
    width: 64 bits
    capabilities: smbios-2.7 dmi-2.7 smp vsyscall32
    configuration: administrator_password=disabled chassis=notebook family=ThinkPad T430s power-on_password=disabled sku=LENOVO_MT_2353 uuid=[REM
OVED]
  *-pnp00:00
$ dpkg-query -W shim-signed-common shim-unsigned linux-*5.11.8* build-essential fakeroot
build-essential 12.9
fakeroot        1.25.3-1.1
linux-headers-5.11.8+   5.11.8+-3
linux-image-5.11.8+     5.11.8+-3
shim-signed-common      1.33+15+1533136590.3beb971-7
shim-unsigned   15+1533136590.3beb971-10
$ lsb_release -dr
Description:    Debian GNU/Linux bullseye/sid
Release:        unstable
$ uname -smr
Linux 5.11.8+ x86_64

Google Chromeの英語文字起こし機能を試す

Google Chromeにリアルタイム文字起こし機能がやってきたようです.

オフラインで文字起こしするとのことでサーバとやり取りしないのはいいですね.
手元の環境では20日に試すと未だ使えませんでしたが,21日に試すと使えるようになっていました.この間Google Chrome自体のアップデートは行われていません.
ChromiumやBrave Browserには対応していないのか現在のところ現れません.最近の感じからするとChromeのみの対応なのかもしれません.

機能を有効にするには設定が必要です.

chromecaption setting

「setting」→「Accessibility」→「Caption」→「Live Caption」をOnにします.すると音声認識ファイルのダウンロードが始まるのでしばらく待ちます.
ダウンロード完了後,適当な英語の動画やオーディオを再生すると字幕が付きます.

chromecaption youtube

これはYoutubeを再生しているところです.上の動画内の字幕はYoutubeの自動文字起こしのもので,下側のがGoogle Chromeの字幕です.ミュートにしても問題なく文字起こしは動作します.

chromecaption local

更に,念の為回線を接続していない状態でローカルの動画やオーディオを再生するとこれもちゃんと文字起こしされました :)
日本語のソースを再生するとそれっぽいところを英語で文字起こししようと頑張っています.キャプションのウィンドウの☓を押して消すとCPU利用率が下がりました.

あとはこの文字起こしされたテキストを保存したり日本語翻訳できると便利なのですが,このテキストはコピーできないようです.Google翻訳でWeb翻訳を試みてもこの部分のテキストは翻訳されないようでした.残念.
拡張機能でこのあたりを実現できるものが出てこないかなと思っています.

現在は英語のみの対応ですが,他の言語にも対応してほしいですね.

環境
$ google-chrome --version
Google Chrome 89.0.4389.90
$ dpkg-query -W google-chrome-stable
google-chrome-stable    89.0.4389.90-1
$ lsb_release -dr
Description:    Debian GNU/Linux bullseye/sid
Release:        unstable
$ uname -m
x86_64

YoutubeLiveの追っかけ再生をstreamlinkで

YoutubeLiveで配信中の映像は配信者が許可していれば先頭から見返すことが出来ます.再生速度を早くして追いつくことも出来ます.
ウェブブラウザでのYoutubeプレイヤーであればあまり意識せずにこれを実現できます.

streamlinkとビデオプレイヤーを使うことで同じようなことが出来ました.

まずは普通に再生すると最新の部分から再生が始まります.(360pを指定しています.)

$ streamlink https://www.youtube.com/watch?v=brrm328XItM 360p

次に --hls-live-restart オプションを付けると最初から再生が始まりました.このときのビデオプレイヤーで再生速度の変更が出来ます.(VLC の場合は「Playback」→「speed」で増減できる)
1.5倍くらいなら問題なさそうです.

$ streamlink --hls-live-restart https://www.youtube.com/watch?v=brrm328XItM 360p

1.5倍速をはじめから指定したいなとVLCのmanを観ても載ってなく,オンラインドキュメントもエラーで見ることが出来なかったので,mpvを使ってみました.

まず mpv で再生速度を1.5倍にするには, --speed=1.5 でいけました.

例 1. man mpvより
--speed=<0.01-100>
       Slow down or speed up playback by the factor given as parameter.
If  --audio-pitch-correction  (on  by  default)  is  used,  playing  with  a speed higher than normal automatically inserts the
scaletempo audio filter.

これをstreamlinkの --player オプションで渡すと,以下のようになって実行して再生が1.5倍で始まります.

$ streamlink --hls-live-restart https://www.youtube.com/watch?v=brrm328XItM 360p --player="mpv --speed=1.5"

ということでとりあえずやりたいことが出来ました :)

これをやって何が嬉しいかというとウェブブラウザを介さないことでウェブブラウザからGPUが利用できない環境でGPUが利用できたり,省メモリだったりするのが嬉しいです.
私はサブマシンに古いマシンを利用してそちらで動かすとウェブブラウザ経由では駒落ちしてしまうけど直接ビデオプレイヤーで実行するときれいに再生されるので助かっています.

環境
$ dpkg-query -W streamlink mpv vlc
mpv     0.32.0-2+b1
streamlink      2.0.0-1
vlc     3.0.12-3
$ lsb_release -dr
Description:    Debian GNU/Linux bullseye/sid
Release:        unstable
$ uname -m
x86_64

Nextcloudでurl共有したpdfをwebに埋め込みたい その2

ドキュメント共有サイトの無料枠を使うのが辛くなったのでNextcloudのURL共有でどうにかならないかなと思っています.
まずはpdfファイルをobjectタグで埋め込む方法を試しました.

この方法のデメリットはcgiを用意しないといけない,pdfを読む気がなくてもページを読み込むとpdfファイルがダウンロードされてしまいページ容量が大きくなってしまう.そしてNextcloudに「<pdfファイル名> が公開リンクからダウンロードされました」という通知がたくさん届いてしまいちょっとうるさいといった感じです.

途中のcgiでキャッシュしてプレビュー用の画像を用意してwebにはそのプレビュー画像を表示しておけばいいのではとcgiを書き換えていました.headで引っ張ってもダウンロードされた扱いになるしdbから実ファイルの場所を探してそこからダウンロードするように,サムネイルもdbから引っ張ってこれるかな?とかやってましたがふとそれだと標準の機能で出来るのではと気づいたので試してみました.

pdf共有URLの末尾に /preview を付けるとプレビュー画像が表示されます.(標準では50MB以下のファイルの場合)

これを利用してこんな感じに書くと,

AsciiDocでの例
[quote,'link:https://files.matoken.org/index.php/s/r7jEJdjiSRzb4nZ[https://files.matoken.org/index.php/s/r7jEJdjiSRzb4nZ]']
link:https://files.matoken.org/index.php/s/r7jEJdjiSRzb4nZ[image:https://files.matoken.org/index.php/s/r7jEJdjiSRzb4nZ/preview[width=100%]]
htmlへ変換した例
<div class="quoteblock">
<blockquote>
<a href="https://files.matoken.org/index.php/s/r7jEJdjiSRzb4nZ"><span class="image"><img src="https://files.matoken.org/index.php/s/r7jEJdjiSRzb4
nZ/preview" alt="preview" width="100%"></span></a>
<div class="attribution">
&#8212; <a href="https://files.matoken.org/index.php/s/r7jEJdjiSRzb4nZ">https://files.matoken.org/index.php/s/r7jEJdjiSRzb4nZ</a>
</div>
</blockquote>
</div>

こういうふうになりました.クリックするとNextcloudのpdfファイルプレビュー画面が開かれ,最近のモダンウェブブラウザではそのまま閲覧できます.

SpeakerDeckなんかでは埋め込んだページでそのまま読むことも出来ますがとりあえずこれならcgiも必要なくNextcloudの標準機能だけ(恐らくNC13以降で可能)でいけるのでそこそこいい感じではないかなと思います.

環境
$ sudo -u www-data php occ --version
Nextcloud 20.0.8
$ dpkg-query -W php mariadb-server apache2
apache2 2.4.38-3+deb10u4
mariadb-server  1:10.3.27-0+deb10u1
php     2:7.3+69
$ lsb_release -dr
Description:    Debian GNU/Linux 10 (buster)
Release:        10
$ uname -m
x86_64

ImageMagickでpdfファイルの1ページ目だけをjpegにする

ImagemMgickのconvertコマンドでpdfをjpegにしようとするとエラーになってしまいました.でもこれは見覚えのあるエラー……どこかにメモした気がするのですが見当たらないのでblogにしてみました.

ImageMagickのセキュリティポリシーを変更してpdfファイルを変換できるようにする

$ convert -geometry 640 /var/tmp/Nextcloud2pdf_cache/HQeSTL5TgcgAPtS.pdf[0] /tmp/HQeSTL5TgcgAPtS.jpg
convert-im6.q16: attempt to perform an operation not allowed by the security policy `PDF' @ error/constitute.c/IsCoderAuthorized/408.
convert-im6.q16: no images defined `/tmp/HQeSTL5TgcgAPtS.jpg' @ error/convert.c/ConvertImageCommand/3258.

セキュリティの問題でImageMagickの設定で無効にしてあるのでこれを有効にします.

$ sudo git -C /etc diff /etc/ImageMagick-6/policy.xml
diff --git a/ImageMagick-6/policy.xml b/ImageMagick-6/policy.xml
index 82a3d0b..0953557 100644
--- a/ImageMagick-6/policy.xml
+++ b/ImageMagick-6/policy.xml
@@ -91,6 +91,6 @@
   <policy domain="coder" rights="none" pattern="PS2" />
   <policy domain="coder" rights="none" pattern="PS3" />
   <policy domain="coder" rights="none" pattern="EPS" />
-  <policy domain="coder" rights="none" pattern="PDF" />
+  <policy domain="coder" rights="read|write" pattern="PDF" />
   <policy domain="coder" rights="none" pattern="XPS" />
 </policymap>

設定を編集後実行するとうまく動きました :)

$ convert -geometry 640 /var/tmp/Nextcloud2pdf_cache/HQeSTL5TgcgAPtS.pdf[0] /tmp/HQeSTL5TgcgAPtS.jpg

pdfファイルの指定ページだけを変換する

ソースファイル名を普通に指定すると, ファイル名-%d.jpg のようなファイルが連番で作成されます.
今回は1ページめだけが欲しいので不必要なファイルがたくさん出来てしまいます.

1ページだけが欲しい場合, ソースファイル名.pdf[0] というようにページ指定して実現できます.この添字は1ページ目が0,2ページめが1のように指定します.

存在しないページ番号を指定するとエラーになります.

$ convert -geometry 640 /var/tmp/Nextcloud2pdf_cache/HQeSTL5TgcgAPtS.pdf[99] /tmp/HQeSTL5TgcgAPtS-99.jpg

Requested FirstPage is greater than the number of pages in the file: 33
   No pages will be processed (FirstPage > LastPage).
convert-im6.q16: no images defined `./HQeSTL5TgcgAPtS-1.jpg' @ error/convert.c/ConvertImageCommand/3258.
環境
$ dpkg-query -W imagemagick
imagemagick     8:6.9.10.23+dfsg-2.1+deb10u1
$ lsb_release -dr
Description:    Debian GNU/Linux 10 (buster)
Release:        10
$ uname -m
x86_64

NotePCのAC電源接続状況を確認してAC電源が切断されたら時間を表示してサスペンドする

IMG_20210313_181855

大きなバッテリーを裏山で使ってみました.昼過ぎから夕方まで使って目盛り半分くらい.家に帰ってからも使い続けましたがなかなかバッテリ切れになりません.

寝る前に電池が来てる感じがしません.また測り直すのは面倒なので以下のようなscriptを書いて寝ました.

$ while [[ `acpi -a | grep on-line` ]]; do sleep 10;done; echo "AC Off-line! (`date +%T`)" | pee cat "xmessage -file - "& pushbullet ; systemctl suspend
AC Off-line! (02:09:56)

acpiコマンドで電源の状況を確認しました.

$ acpi -a
Adapter 0: on-line
$ acpi -a
Adapter 0: off-line

acpiコマンドがない場合sysを見るといいかもしれません.acpidがない場合は無理かな?

$ while [[ `cat /sys/class/power_supply/AC/online` == 1 ]]; do sleep 10;done; echo "AC Off-line! (`date +%T`)" | pee cat "xmessage -file - "& pushbullet ; systemctl suspend

10秒毎に電源状況を確認してAC電源がOffになったらコンソールとXとPushBulletにメッセージを送信してサスペンドするようにしました.

てことでPCの動作状況にもよるでしょうが今回は約12時間動作しました.

今回バッテリー(3.7V DC)からAC 100Vに変換,更にDC(20V)変換しているので変換効率が悪そうです.DC12V出力も出来るようなのでそこからDC-DC変換するようにすると効率よくなってさらに時間が伸びそうな気がします.

環境
$ sudo lshw -c system -sanitize | head
computer
    description: Notebook
    product: 23533KJ (LENOVO_MT_2353)
    vendor: LENOVO
    version: ThinkPad T430s
    serial: [REMOVED]
    width: 64 bits
    capabilities: smbios-2.7 dmi-2.7 smp vsyscall32
    configuration: administrator_password=disabled chassis=notebook family=ThinkPad T430s power-on_password=disabled sku=LENOVO_MT_2353 uuid=[REM
OVED]
  *-pnp00:00
$ dpkg-query -W acpi x11-utils
acpi    1.7-1.1
x11-utils       7.7+5
$ lsb_release -dr
Description:    Debian GNU/Linux bullseye/sid
Release:        unstable
$ uname -m
x86_64

Nextcloudでurl共有したpdfをwebに埋め込みたい

スライドやドキュメントを共有するのにSpeakerDeckやedockrを使っています.(SlideShareは無料アカウントで再アップロードができなくなってしまってから使わなくなりました.)
SpeakerDeckの無料での制限で100アップロードまででそろそろいっぱい,edockrはしばらくしたら消えてしまうということを最近知りました.

pdfファイルを共有するだけならNextcloudでのURL共有を使えばいいのですが,webに埋め込むことが出来ません.Nextcloudの機能やアプリにそういったものがあるといいのですが,セキュリティの問題から実装されていません.

とりあえず雑な方法ですが,こんな感じで実現してみました.

Nextcloud URL共有リンクからpdfファイルを出力する

Nextcloudの公開URLの内容をpdfとして出力します.実行権を付けてcgiとして設定します.

#!/usr/bin/perl
use strict;
use warnings;
use LWP::Simple;
use IO::Handle;
STDOUT->autoflush(1);

$ARGV[0] = "" unless defined $ARGV[0];
my $url = $ARGV[0];
if( $url !~ /\/download$/ ){
  $url = $url . "/download";
}
print "Content-Type: application/pdf\n\n";
getprint($url);

とりあえずこんな感じでcgiの後ろにNextcloud公開URLを付けてアクセスするとブラウザでpdfを見ることができるようになりました.

embedタグでwebに埋め込む

上で作ったcgiをobjectタグで埋め込んでみるととりあえず埋め込みが出来ました.このとき height% を指定してもサイズが変わらないようでした.(Debian sid amd64 の chromium 88.0.4324.146-1, firefox 86.0.1-1 で確認)

<embed src="http://cgi.example.com/pdf.cgi?http://nextcloud.example.com/index.php/s/XXXXXXXXXXXXXXX" type="application/pdf" width="640px" height="480px">

とりあえずそれっぽいことは出来ましたが,この方法ではpdfを読まなくてもページ読み込み時にpdfを全部読み込んでしまうようなのであまりよろしくない感じです.このあたりはSpeakerdeckなどはちゃんとしてていいですね.

とりあえずはリンクで共有かな?

Nextcloudの2要素認証が出来ないときに管理者が1度限りのワンタイムコードを発行できる「Two-Factor Admin Support」

Nextcloudユーザが2要素認証を出来ないときにNextcloud管理者が48時間有効な1度限りのワンタイムコードを作成することができる「Two-Factor Admin Support」を試してみました.

「Two-Factor Admin Support」install
$ sudo -u www-data php occ app:install twofactor_admin

occコマンドで導入しました.WebインターフェイスからでもOKです.

nextcloud towfactor admin01

導入後,管理者アカウントで「設定」→「管理」→「セキュリティ」の「Two-Factor Admin」が出来ています.この「User ID」のテキストボックスにワンタイムコードを発行したいユーザIDを入力して「Generate」を押すと48時間有効なワンタイムコードが発行されます.このコードをユーザに伝えてログインしてもらいます.

occコマンドでのワンタイムコードの発行
$ sudo -u www-data php occ twofactorauth:admin:generate-code $USERID
There is an existing code that will be overwritten.

Generated new one-time code for test01: 163929
This code is valid for 48 hours.

occコマンドでも発行できます.

nextcloud towfactor admin02

該当ユーザはユーザID/パスワードを入力した後の2要素認証で「Admin code」という選択肢が増えるのでそれを選びます.

nextcloud towfactor admin03

管理者に教えてもらったワンタイムコードを入力してログインします.

TOTPのデバイスを壊してしまったり家に忘れてきたとかいったときに便利そうです.(数が少なければ)

環境
$ sudo -u www-data php /var/www/files.matoken.org/occ app:list | grep twofactor_admin:
  - twofactor_admin: 3.0.0
$ sudo -u www-data php occ --version
Nextcloud 20.0.8
$ dpkg-query -W php mariadb-server apache2
apache2 2.4.38-3+deb10u4
mariadb-server  1:10.3.27-0+deb10u1
php     2:7.3+69
$ lsb_release -dr
Description:    Debian GNU/Linux 10 (buster)
Release:        10
$ uname -m
x86_64

Nextcloudのmailアプリのアップデートに失敗してNextcloudが使えなくなって困る

Nextcloudアプリのアップデートを行ったところmailの処理中にコケてしまったようです.

$ sudo -u www-data php occ app:update --all
richdocuments new version available: 3.7.17
richdocuments updated
forms new version available: 2.2.1
forms updated
mail new version available: 1.9.2
An unhandled exception has been thrown:
Error: Call to undefined method OCA\Mail\Db\MessageMapper::findWithEmptyMessageId() in /var/www/files.matoken.org/apps/mail/lib/Migration/AddMissingMessageIds.
php:55
Stack trace:
#0 /var/www/files.matoken.org/lib/private/Repair.php(112): OCA\Mail\Migration\AddMissingMessageIds->run(Object(OC\Repair))
#1 /var/www/files.matoken.org/lib/private/legacy/OC_App.php(1042): OC\Repair->run()
#2 /var/www/files.matoken.org/lib/private/legacy/OC_App.php(979): OC_App::executeRepairSteps('mail', Array)
#3 /var/www/files.matoken.org/lib/private/Installer.php(206): OC_App::updateApp('mail')
#4 /var/www/files.matoken.org/core/Command/App/Update.php(116): OC\Installer->updateAppstoreApp('mail', false)
#5 /var/www/files.matoken.org/3rdparty/symfony/console/Command/Command.php(255): OC\Core\Command\App\Update->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#6 /var/www/files.matoken.org/3rdparty/symfony/console/Application.php(1000): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#7 /var/www/files.matoken.org/3rdparty/symfony/console/Application.php(271): Symfony\Component\Console\Application->doRunCommand(Object(OC\Core\Command\App\Update), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#8 /var/www/files.matoken.org/3rdparty/symfony/console/Application.php(147): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#9 /var/www/files.matoken.org/lib/private/Console/Application.php(215): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#10 /var/www/files.matoken.org/console.php(100): OC\Console\Application->run()
#11 /var/www/files.matoken.org/occ(11): require_once('/var/www/files....')
#12 {main}mk@www6073uo:/var/www/files.matoken.org

再度実行すると処理は進んだようですが,縮退モードのような感じになっています.この状態でNextcloudのWebにアクセスするとアップデートを求められて利用できません.

$ sudo -u www-data php occ app:update --all
Nextcloud or one of the apps require upgrade - only a limited number of commands are available
You may use your browser or the occ upgrade command to do the upgrade
files_linkeditor new version available: 1.1.4
files_linkeditor updated

どうしたもんかととりあえず原因であろうmailをアップデートしようとするとすでに最新のようです.
次にmailを無効化してみました.するとNextcloud Webが利用できるようになりました.
一旦削除してインストールし直したほうが確実だろうなと思いつつmailを有効化するとNextcloudもmailも利用できるようになりました.

$ sudo -u www-data php occ app:update mail (1)
Nextcloud or one of the apps require upgrade - only a limited number of commands are available
You may use your browser or the occ upgrade command to do the upgrade
$ sudo -u www-data php occ app:disable mail (2)
Nextcloud or one of the apps require upgrade - only a limited number of commands are available
You may use your browser or the occ upgrade command to do the upgrade
mail 1.9.2 disabled
$ sudo -u www-data php occ app:enable mail (3)
mail 1.9.2 enabled
  1. mailアプリをアップデートしても反応はない
  2. mailアプリを無効化してNextcloud復旧
  3. mailアプリを有効化

occ app:disable mail の後 occ app:remove mail && occ app:install mail したほうが確実だと思います.

ちなみにNextcloud Hub以外のあまりメジャーでないアプリなどをインストールしてうまく動かないときにもNextcloudが動かなくなることがあります.そういうときも occ app:disable で復旧できるので覚えておくと助かります.

環境
$ sudo -u www-data php occ app:list | grep \ mail:
  - mail: 1.9.2
$ sudo -u www-data php occ --version
Nextcloud 20.0.8
$ dpkg-query -W php mariadb-server apache2
apache2 2.4.38-3+deb10u4
mariadb-server  1:10.3.27-0+deb10u1
php     2:7.3+69
$ lsb_release -dr
Description:    Debian GNU/Linux 10 (buster)
Release:        10
$ uname -m
x86_64