2021年3月13日土曜日

S.M.A.R.T.値などで異常を示したST3000DM008で遊んでみよう

新規購入したHDDの初期不良のチェックやRAIDアレイの再構成が一段落ついたので、 先日故障が発覚したHDD(Seagate Barracuda 3.5, ST3000DM008-2DM166)で遊んでみたいと思います。

とにかくドライブのサイズがそれなりに大きいので、一つのコマンドの結果が返ってくるまでに5時間など当たり前なので、一日一コマンドづつしか入力できないのがもどかしいのですが、まあ折角ですので、これまで何度もやっているとはいえ、訓練を重ねることは悪いことではありません。
今回はまず、不良セクタを何とかしたいと思います。


今回の状況としては、/dev/sddとして接続し、ext4の単体ドライブとしてmkfs.ext4をしなおしたうえでrsyncコマンドで元のRAIDの内容をコピーしてある状況を作りました。

まずは異常セクタの特定から行いたいのですが、前回書いた通り、smartctl -t longテストでは異常なしとか平気で言い放つ始末で手に負えません。

実際には以下のパラメータが48まで上昇しているにもかかわらず、です。

・197 Current_Pending_Sector
・198 Offline_Uncorrectable

もはやHDDの自己テスト機能がダメになっているのかもしれません。

そこで、badblocksコマンドを用いて異常セクタを検出したいと思います。

まあ、念のため、再度ブロックサイズを確認します。

1
2
# tune2fs -l /dev/sdd1|grep -i "block size"
Block size:               4096

このパラメータをbadblocksに与えて検査させます。
1
2
3
4
# nohup badblocks -b 4096 -vs -o badblocks.txt /dev/sdd1&
tail -f nohup.out
Checking blocks 0 to 732566271
100.00% done, 5:23:20 elapsed. (139/0/0 errors)
ということで、五時間半かかって、139セクタもの不良セクタが検出されてしまいました。

この段階でのsmart値は以下の通りです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
  1 Raw_Read_Error_Rate     0x000f   097   093   006    Pre-fail  Always       -       40328485
  3 Spin_Up_Time            0x0003   096   096   000    Pre-fail  Always       -       0
  4 Start_Stop_Count        0x0032   100   100   020    Old_age   Always       -       6
  5 Reallocated_Sector_Ct   0x0033   100   100   010    Pre-fail  Always       -       8
  7 Seek_Error_Rate         0x000f   076   060   030    Pre-fail  Always       -       49566908
  9 Power_On_Hours          0x0032   063   063   000    Old_age   Always       -       32571
 10 Spin_Retry_Count        0x0013   100   100   097    Pre-fail  Always       -       0
 12 Power_Cycle_Count       0x0032   100   100   020    Old_age   Always       -       6
183 Runtime_Bad_Block       0x0032   100   100   000    Old_age   Always       -       0
184 End-to-End_Error        0x0032   100   100   099    Old_age   Always       -       0
187 Reported_Uncorrect      0x0032   001   001   000    Old_age   Always       -       262
188 Command_Timeout         0x0032   100   100   000    Old_age   Always       -       0 0 0
189 High_Fly_Writes         0x003a   099   099   000    Old_age   Always       -       1
190 Airflow_Temperature_Cel 0x0022   076   060   045    Old_age   Always       -       24 (Min/Max 20/26)
191 G-Sense_Error_Rate      0x0032   100   100   000    Old_age   Always       -       0
192 Power-Off_Retract_Count 0x0032   100   100   000    Old_age   Always       -       4
193 Load_Cycle_Count        0x0032   073   073   000    Old_age   Always       -       55928
194 Temperature_Celsius     0x0022   024   040   000    Old_age   Always       -       24 (0 13 0 0 0)
197 Current_Pending_Sector  0x0012   094   094   000    Old_age   Always       -       1112
198 Offline_Uncorrectable   0x0010   094   094   000    Old_age   Offline      -       1112
199 UDMA_CRC_Error_Count    0x003e   200   200   000    Old_age   Always       -       0
240 Head_Flying_Hours       0x0000   100   253   000    Old_age   Offline      -       32556h+15m+05.395s
241 Total_LBAs_Written      0x0000   100   253   000    Old_age   Offline      -       25786278431
242 Total_LBAs_Read         0x0000   100   253   000    Old_age   Offline      -       1151768457351

いやあ、すげえ。Current_Pending_Sector  とOffline_Uncorrectable   が1112にまで上昇してしまいました。
これから試す方法の挙動が楽しみです。

さて、まずは実際にbadblocksコマンドで得たセクタ番号がHDD自身から聞けるかどうか、smartctl -t shortで尋ねてみました。

1
2
# 1  Short offline       Completed: read failure       90%     32571         -
# 2  Extended offline    Completed without error       00%     32452         -


全然教えてくれる気はないようです。

しかし、前回、異常が発生しているにもかかわらずエラーなし(#2です)で正常終了していたのが、read failureで異常終了(#1です)しているのはせめてもの事でした。

異常なしっていう時点でおかしいですもの。


まあ、HDDが異常セクタを教えてくれないとのことですので、それならばbadblocksで検出した139の異常セクタをどうにかすればsmart値はどうなるのかを見ていきたいと思います。


その前に、異常セクタにあるファイルを削除するため、先ほどのbadblocksコマンドで生成された badblocks.txt に記録されているセクタ番号をもとに、debugfsコマンドでセクタ番号から使用されているinode番号を取得して、そのinode番号をもとにファイル名を特定します。


無論、すぐに廃棄する予定のHDDでここまでする必要はないのですが、せっかくの演習ですから壊れても惜しくない大容量HDD(いや、もう壊れているのですが)、有効活用してみたいと思います。


まずは指定したセクタに何らかのデータが記録されているかを調べるには以下です。

セクタ番号が524726232として、icheck <セクタ番号>で調査します。

1
2
3
4
# debugfs -R "icheck 524726232" /dev/sdd1
debugfs 1.42.9 (28-Dec-2013)
Block   Inode number
524726232       117966080

ばっちり使われています。

使われていない場合は次のような表示になります。
1
2
3
4
# debugfs -R "icheck 620236906" /dev/sdd1
debugfs 1.42.9 (28-Dec-2013)
Block Inode number
620236906 <block not found>

これを139セクタ分繰り返します。

ファイル名を得るには
1
#  debugfs -R "ncheck 117966080" /dev/sdd1
というように、"ncheck inode番号" を実行しますと、ファイル名が表示されます。
inode番号は重複する場合がありますので、sortしてuniqしたほうがいいと思います。
数が数ですので、awkなりperlなりpythonなり、スクリプトを書いたほうが安全かと思います。

さて、今回のケースではファイル数に換算すると46ファイルでした。
でかいファイルが配置されていたセクタが多かったようです。

早速それらをunlinkして、smart値を見てみますと、特に意味がある変化は見られません。
当たり前といえば当たり前ですが。

お次はddコマンドで0を書き込んでセクタを代替させる作業を行います。
139セクタすべてを0で埋めますが、その前に1セクタだけやって、smart値がどう変化するかを見てみたいと思います。

1
2
3
4
5
6
7
8
9
10
11
12
13
# dd if=/dev/zero of=/dev/sdd1 bs=4096 count=1 seek=524726232
1+0 レコード入力
1+0 レコード出力
4096 バイト (4.1 kB) コピーされました、 0.00141101 秒、 2.9 MB/秒
# sync
# smartctl -a /dev/sdd1
ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
 (略)
  5 Reallocated_Sector_Ct   0x0033   100   100   010    Pre-fail  Always       -       8
 (略)
197 Current_Pending_Sector  0x0012   094   094   000    Old_age   Always       -       1104
198 Offline_Uncorrectable   0x0010   094   094   000    Old_age   Offline      -       1104
 (略)

おやおや、Reallocated_Sector_Ct   の値は変化がありませんが、Current_Pending_Sector  とOffline_Uncorrectable   の値が2ポイント増えてしまいました。なかなか興味深い事象なので後で遊ぶとして、あと138セクタあるので、残りは一括してスクリプトを組んでゼロで埋めてしまいます。

その結果、
1
2
3
  5 Reallocated_Sector_Ct   0x0033   100   100   010    Pre-fail  Always       -       8
197 Current_Pending_Sector  0x0012   100   094   000    Old_age   Always       -       0
198 Offline_Uncorrectable   0x0010   100   094   000    Old_age   Offline      -       0
Current_Pending_Sector  とOffline_Uncorrectable   の値がゼロになり、代替されたセクタが増えていません。
これ、書き込みが成功した場合は代替しないっていうHDDがあることは知っていましたが、このHDDもその一味なのでしょうか。

念のため、これらのセクタを下手に使ってしまわないようにファイルシステムに"コイツはダメだ"と記録しておきます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# fsck.ext4 -l badblocks.txt /dev/sdd1
e2fsck 1.42.9 (28-Dec-2013)
/dev/sdd1: Updating bad block inode.
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Free blocks count wrong for group #18928 (23698, counted=23699).
Fix<y>? yes
Free blocks count wrong for group #19312 (24543, counted=24544).
Fix<y>? yes
Free blocks count wrong for group #20416 (24543, counted=24544).
Fix<y>? yes
Free blocks count wrong for group #22000 (24543, counted=24544).
Fix<y>? yes
Free blocks count wrong for group #22032 (24542, counted=24544).
Fix<y>? yes
Free blocks count wrong (63487139, counted=63487145).
Fix<y>? yes
/dev/sdd1: ***** FILE SYSTEM WAS MODIFIED *****
/dev/sdd1: 97313/183148544 files (1.5% non-contiguous), 669079127/732566272 blocks

ま、結果は信用できませんが、仕上げに自己テストを行わせます。
1
# smartctl -t long /dev/sdd
結果は後日のお楽しみです。(どうせwithout errorでしょうねぇ)

それにしても、3TBという容量が容量なので、こんな危なっかしいHDDをだましだまし使うということは難しい感じです。
廃棄以外にちょっと考えられません。

6TBとか8TBとかがボリュームゾーンになってきている様子ですが、今後ますますトラブル発生即交換・廃棄という運用じゃないととてもやっていけませんねえ。
貧乏性にはつらい選択です。

結果として、頓死しないでずるずる生き延びる、なんだかおもしろい機材が手に入ってしまったので、今後も時間があれば何らかのネタを仕込んでみたい気もしますが、まずは来月あたりにもう一度badblocksコマンドで総なめしてみて、何か面白いことが起きるかどうかですかねえ。

まずは今回はこんなところでしょうか。

ここまでお読みいただき、ありがとうございました。

2021年3月11日木曜日

3年6か月目にST3000DM008に異常発生、WD40EZRZ-RT2購入

一昨日、自宅サーバにて二台のST3000DM008でRAID1を構成していた一台に異常が発生していることが発覚しました。
ペアを組んでいるもう一台のST3000DM008は何の問題もなく元気に稼働しています。

異常は毎週のraid-checkで検出されていました。
よくよく調べてみると、先月のsyslogにすでに異常が報告されていることが分かりました。
smartctlからもmdadmからもメールが来なかったのですっかり油断していました。

2017年6月に運用を開始して以来、メーカーが保証していない24時間365日な自宅サーバ上での使用でこれだけの期間、頑張ってくれたことに感謝です。

実際のところ、ST3000DM001の型番だけ変更品なんじゃないかという疑念が付きまとっていた本製品だけに、一層感謝の念が深まります。


障害の内容は、syslogによるとアクセス不能なセクタが発見されていました。
1
2
3
4
5
6
7
8
9
10
11
12
13
Mar  7 05:57:53 ***** kernel: ata3.00: exception Emask 0x0 SAct 0x100000 SErr 0x0 action 0x0
Mar  7 05:57:53 ***** kernel: ata3.00: irq_stat 0x40000008
Mar  7 05:57:53 ***** kernel: ata3.00: failed command: READ FPDMA QUEUED
Mar  7 05:57:53 ***** kernel: ata3.00: cmd 60/00:a0:00:17:46/01:00:45:01:00/40 tag 20 ncq 131072 in#012         res 41/40:00:38:17:46/00:01:45:01:00/00 Emask 0x409 (media error) &lt;f&gt;
Mar  7 05:57:53 ***** kernel: ata3.00: status: { DRDY ERR }
Mar  7 05:57:53 ***** kernel: ata3.00: error: { UNC }
Mar  7 05:57:53 ***** kernel: ata3.00: configured for UDMA/133
Mar  7 05:57:53 ***** kernel: sd 2:0:0:0: [sdc] tag#20 FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE cmd_age=3s
Mar  7 05:57:53 ***** kernel: sd 2:0:0:0: [sdc] tag#20 Sense Key : Medium Error [current] [descriptor]
Mar  7 05:57:53 ***** kernel: sd 2:0:0:0: [sdc] tag#20 Add. Sense: Unrecovered read error - auto reallocate failed
Mar  7 05:57:53 ***** kernel: sd 2:0:0:0: [sdc] tag#20 CDB: Read(16) 88 00 00 00 00 01 45 46 17 00 00 00 01 00 00 00
Mar  7 05:57:53 ***** kernel: blk_update_request: I/O error, dev sdc, sector 5457188664
Mar  7 05:57:53 ***** kernel: ata3: EH complete
驚いてsmartctlで確認したところ、SMART Error Log Version: 1には既に109件もエラーが記録されており、かつ、Reallocated_Sector_Ctの値が8になっていました。

SMART Error Logはこんな感じでした。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
SMART Error Log Version: 1
ATA Error Count: 109 (device log contains only the most recent five errors)
        CR = Command Register [HEX]
        FR = Features Register [HEX]
        SC = Sector Count Register [HEX]
        SN = Sector Number Register [HEX]
        CL = Cylinder Low Register [HEX]
        CH = Cylinder High Register [HEX]
        DH = Device/Head Register [HEX]
        DC = Device Command Register [HEX]
        ER = Error register [HEX]
        ST = Status register [HEX]
Powered_Up_Time is measured from power on, and printed as
DDd+hh:mm:SS.sss where DD=days, hh=hours, mm=minutes,
SS=sec, and sss=millisec. It "wraps" after 49.710 days.
 
Error 109 occurred at disk power-on lifetime: 32432 hours (1351 days + 8 hours)
  When the command that caused the error occurred, the device was active or idle.
 
  After command completion occurred, registers were:
  ER ST SC SN CL CH DH
  -- -- -- -- -- -- --
  40 51 00 ff ff ff 0f  Error: UNC at LBA = 0x0fffffff = 268435455
 
  Commands leading to the command that caused the error were:
  CR FR SC SN CL CH DH DC   Powered_Up_Time  Command/Feature_Name
  -- -- -- -- -- -- -- --  ----------------  --------------------
  60 00 00 ff ff ff 4f 00  19d+18:25:46.787  READ FPDMA QUEUED
  60 00 00 ff ff ff 4f 00  19d+18:25:46.754  READ FPDMA QUEUED
  60 00 00 ff ff ff 4f 00  19d+18:25:46.143  READ FPDMA QUEUED
  60 00 00 ff ff ff 4f 00  19d+18:25:46.015  READ FPDMA QUEUED
  60 00 00 ff ff ff 4f 00  19d+18:25:46.014  READ FPDMA QUEUED

しかしながら、
1
SMART overall-health self-assessment test result: PASSED
なのでsmartctlはメールを飛ばさなかったようです。
ついでにセルフテストを行ってみましたが、こちらも
1
1  Extended offline    Completed without error       00%     32452         -
といわれてしまい、成功終了してしまいました。

兎にも角にも、RAIDが縮退運転に入る前に気づけたことは幸いでした。
早速、気づいたその日にすぐに代替用HDDの選定に入りましたが、最近の手ごろな価格のHDDってほとんどが瓦磁気記録方式(以下SMR)なのでびっくりしました。
確かに、SMRの普及が進んでいるとは噂程度には聞き及んでいたのですが、ちょっと考えてしまいました。

SMRと一言で言っても、大抵はHDDの外周部分をCMRとして使って、あとでゆっくりSMR方式の内周部分に移動する方式が主流のようです。
そのため、毎週テラバイト単位(ベアドライブ単位で丸ごとだから)でのバックアップの処理のパフォーマンスが極端に低下する(CMRとして記録できる領域を超えてしまうため)懸念を抱きました。
また、CMRとして利用するシリンダを酷使することによる耐久性はどうなのかというのも、もう少々、できれば数年、様子を見たいところです。
また、gitでのソース管理などでも、細かいファイルが大量に発生してしまうのですが、これの処理のパフォーマンスも気になります。

まあ、所詮は自宅サーバですし、あまり気にしても仕方がないのですが、面倒になったのでとにかくCMRの製品にしようと思って探してみました。

もともと3TBのHDDだったので3TB近辺で探すと、現在は4TBがお安いようですね。
そのため、1TBはRAIDとしては使えませんが4TBのHDDを探してみると、あっさりWD40EZRZ-RT2という製品が見つかりました。これはCMRなんだそうです。
お値段は8千円。SMR方式の同容量のHDDと比べても最大でも千円前後しか価格差はないようです。

今回異常を示したHDDの先々代がWDでしたが、二年も持たず故障したので、若干気がかりですが、これは我ながら難癖でしょう。
結局のところこういうのはどのメーカでも同じことですし、そもそもメーカが保証しない連続運用が前提な使い方をする以上、すべては自己責任です。
さっそく注文して取り寄せました。

とりあえず例によってmdadmでraid1アレイから故障したHDDをfailさせてremoveします。
(たとえばこんな感じです。sdcが今回壊れたHDDです)。
1
2
mdadm --manage /dev/md0 --fail /dev/sdc1
mdadm --manage /dev/md0 --remove /dev/sdc1
その後、障害が発生したHDDをサーバから物理的に抜去するか、そのまま接続するなら別RAIDに仮参加させるなど元のRAIDアレイに戻らないように工夫した後、 新規購入したHDDのパーティションを元のRAIDアレイのサイズと同じサイズで切って追加します。


パーティションを切る際、partedで開始位置と終了位置をセクタ単位で指定したい場合はセクタ番号の後ろにsをつければ問題ありません。partedでprintコマンドでセクタ単位で表示させたい場合は、
(parted) unit s
とすると表示できます。
もっとも、fdisk -l で事前に見ておいたほうが楽だと思います。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# parted /dev/sdc
(parted) mklabel gpt
(parted) mkpart
パーティションの名前?  []? SDC1-WD4T
ファイルシステムの種類?  [ext2]? xfs
開始? 2048s
終了? 5860532223s
(parted) set 1 raid on
(parted) p
モデル: ATA WDC WD40EZRZ-22G (scsi)
ディスク /dev/sdc: 4001GB
セクタサイズ (論理/物理): 512B/4096B
パーティションテーブル: gpt
ディスクフラグ:
 
番号  開始    終了    サイズ  ファイルシステム  名前       フラグ
 1    1049kB  3001GB  3001GB                    SDC1-WD4T  raid

その後、partedで余った1TBのパーティションも追加します。
これは正確な数値である必要はないので、開始位置をサイズ、終了位置を100%といったようなアバウトな指定で十分です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(parted) mkpart
パーティションの名前?  []? SDC2-WD4T
ファイルシステムの種類?  [ext2]? xfs
開始? 3001GB
終了? 100%
(parted) p
モデル: ATA WDC WD40EZRZ-22G (scsi)
ディスク /dev/sdc: 4001GB
セクタサイズ (論理/物理): 512B/4096B
パーティションテーブル: gpt
ディスクフラグ:
 
番号  開始    終了    サイズ  ファイルシステム  名前       フラグ
 1    1049kB  3001GB  3001GB                    SDC1-WD4T  raid
 2    3001GB  4001GB  1000GB                    SDC2-WD4T

余談ですが、もちろん、こんなアバウトな指定のしかたでも、きっちりパーティション2はパーティション1の次のセクタから確保されています(unit sしてprintすればわかります)。
こういった地味だけどとても便利で親切なコマンドを作る気配りというのは、下手をすると余計なお世話になってしまうために目には見えないけれど実際には相当負担が大きいのですが、それをあえてするプログラマの心意気に頭が下がります。

そして、上記で生成したパーティションをアレイに追加すればリカバリが始まります。
1
# mdadm --add /dev/md0 /dev/sdc1

今回のリカバリは夜の20時30分に開始して翌未明02時16分に完了しました。
六時間弱、かあ。するとリカバリ速度は約141,963KB/秒ですね。

ただ・・・容量違いのHDDでRAID1を組むと、新しくて、しかも大きい容量のHDDのほうが先に壊れた経験があるので、今回は先例通りにならないことを願うばかりです。

余談ですが、容量が大きいHDDが先に死んでしまったときに生き残ったHDD(ST31000528AS)は2009/04/24から現在まで元気に活躍していました。
彼の初代の相棒はWD10EADS-00L5B1(2009/04/24運用開始、2011/03/吉日死亡)、次の相棒がST2000DL003(2011/3/22運用開始、2017/06/21死亡)でした。
その後、二代目の相棒の死亡を機にRAIDアレイを引退。
余生をPCクライアントのバックアップ置き場として活躍するものの、2021年3月10日、容量の小ささと古さから廃棄処分となりました。
こちらも、本当によく働いてくれました。
ご苦労様でした。ありがとうございました。

あとは自己診断の結果待ちですが、45,180秒かかるそうなので、初期不良の判定はもうちょっと先になりそうです。
さらに故障が判明してから停止していたrsyncによるraidアレイのバックアップ先との同期やらがあるので当分先の話になりますが、hdparmやddコマンドを用いての単体のHDDの転送速度の実測とか負荷がかかる試験をいろいろ試したいのですが、徐々に進めたいと思います。

ネタのつもりで買ったST3000DM008がここまでしてくれたので、ちょっとうれしくて思わずこのような駄文をひねくってしまいました。
お読みいただきありがとうございました。

---
2021/03/11 追記
異常が発生したST3000DM008をmkfsしなおして、rsyncコマンドでraid1の中身を全コピーしてみたところ、何の異常もなく終了してしまいました。結果は以下の通りです。
1
2
sent 2.80T bytes  received 1.69M bytes  139.56M bytes/sec
total size is 2.81T  speedup is 1.00

RAID1のリカバリ時間とほぼ同等ですかね。おおよそ五時間半かかりました。
それにしても、何の異常もなく正常終了してしまうのには困りました・・・
dmesgにもmessagesにもsmartdctl -aの結果にも、まるで何も記録されていません。
RAIDのアレイ構成員としては恐ろしいのでスペアに指定することなんか想像もできませんが、それはさておいて、3TBもの領域でどう遊んでいいやら。
貧乏性の悩みは尽きませんが、かといって、なんらかのネタを思いつければいいのですが・・・

2021年2月25日木曜日

気象庁のホームページが更新

チラシの裏です。


個人用ホームページの天気予報欄の表示がおかしかったので調べたら、リニューアルなさったんですね。ちっとも知りませんでした。


Android用のウィジェットなど、いくつか依存するアプリを作っていたのですが、まあ、もう当時のような気力は戻ってこないでしょうねぇ。

もう10年近く前に作ったアプリが現役で動いていただけでも御の字ってところでしょうか。


本来なら気象業務支援センターからデータを買わないといけないんでしょうけど・・・やっぱり個人では難しいです。

結局、「気象庁ホームページのコンテンツの利用について」で許されている範囲内で気象庁の負荷にならないように極力注意をしたうえで、ページからスクレイピングを行って実装していました。


ただ一つだけ、冒頭に触れたページですが、具体的には単に注警報や天気図、天気予報とかアメダス値がパッと見られるページなのですが、これがまた個人的には実に便利でしたので、再度実装するとしたらどうしたらいいのかな、とちょっとhtmlページのソースを拝見しました。

設計思想からしてすごい変わりようですね。

従来はサーバ側で全部作っておいて、静的なページとして配信していましたが、今回はhtmlで記述する部分はひな形だけで、データ自身は別個にそれぞれのホームページの閲覧者のブラウザから直接サーバに非同期に通信して取得して、そのデータを(ある程度の加工を行っているケースもありましたが)ひな形に当てはめていく形式になっていました。


その非同期で取得するデータの形式はjsonでした。

jmaさんといえば一時期全然必要性を感じない電文やマイコンで直接処理するような電文にもXML化を推進する勢いでしたのに、どうしちゃったんでしょうか。

しかしjsonを採用してくれたおかげで、電文形式が極めて簡素で、かつ大変利用しやすい形式にまとめられているので、簡単に個人用ページを作り替えることができそうです。無論、ブラウザ上から直接ajaxでjsonを取得しちゃうと毎回ページを閲覧するたびに気象庁にクエリが飛ぶので、それは最低でも天気予報が更新される一日三回までに抑える必要があるので、ひと手間は必要ですが。


それにしても、ちょっと引っかかるのは、jmaさんがホームページに広告を掲載する決断を下したことです。

jsonのデータって果たしてjmaさん的に「気象庁ホームページで公開している情報」に該当するのでしょうか。

XMLデータは気象業務支援センターの営業を邪魔しない程度に遅らせてjmaさんのホームページから入手できますが、これは堂々とその配布のための専用ページも設けられているため、「気象庁ホームページで公開している情報」に該当するでしょう。

一方、jsonデータに関する記述は現時点ではどこにも見当たらず、かつ、それだけではホームページを構成していません(ひな形に当てはめて初めてホームページとして完成します)ので、jmaさんが何らかのアナウンスメントを出すまでは、愛知県岡崎市の例もありますし、当面は出来上がったページへリンクを張る程度にとどめ、様子を見たほうが良いかもしれません。

多少遲くていいなら(そして煩雑なXMLでもいいなら)府県予報でもいいわけですから、おいおい考えていきたいと思います。


それにしても、前代のホームページは19年間も現役だったそうです。

本当にお世話になりました。ありがとうございます。



2020年11月3日火曜日

MoUsoCoreWorkerがスリープを阻害する

ここ数か月か、Windows10がWindows Updateで何かしらシステムがアップデートされて以後、スリープができなくなるという現象に見舞われています。


その際、powercfg.exe /requestsを実行してみると、

C:\WINDOWS\system32>powercfg /requests
DISPLAY:
なし。

SYSTEM:
なし。

AWAYMODE:
なし。

実行:
[PROCESS] \Device\HarddiskVolumeX\Windows\System32\MoUsoCoreWorker.exe
USO Worker

PERFBOOST:
なし。

ACTIVELOCKSCREEN:
なし。

という結果が得られる場合があります。

これは太字のMoUsoCoreWorker.exeがシステムに対して「スリープしちゃイヤン」というお願いをし、それをシステムが聞き入れているという意味です。

「よし、MoUsoCoreWorkerが原因なんだな!ぶっ殺してやる!!」とか言ってタスクマネージャを起動してプロセスをkillする前に、まず試してもらいたいことがあります。


まず、このMoUsoCoreWorkerはWindows Updateの眷族で、Windows Updateとズブズブの関係です(そらそうだ)。

で、Windows Updateでアップデートを行わせたい場合、こいつが出張ってきてWindows Update本体(といえばいいのかな?)が活動中にシステムがスリープしてしまわないように邪魔をする仕事もします。

この時点で、新しいアップデートファイルがMS側に用意されていることはMoUsoCoreWorkerにはわかっています。

こういったケースの場合にMoUsoCoreWorkerによるスリープの阻害が発生していることを数回確認しました。


なお、これは、「オプションの品質更新プログラムがあります」という表示とは別物です。

重要なので再度繰り返させていただきますが、別物です。

ここからがお笑いなのですが、Windows Update本体はこの新しいアップデートファイルを何日も見つけられないまま最新の状態です」と強弁し続ける場合があります。


つまり、オプション以外のアップデートがあることはMoUsoCoreWorkerにはわかっているが、それをユーザに提示できず、かつWindows Update本体がそのアップデートをダウンロードしてシステムを更新できないという状況が現出します。


これは、システムを再起動しても、「設定」画面の「更新とセキュリティ」の「Windows Update」画面で「更新プログラムのチェック」ボタンを連打しても変わらないことがあります。

そうなると、ユーザには何が原因なのか外見からはわかりません。

憎きはMoUsoCoreWorkerただ一人、きゃつを封じるためにはどんな手でも使わなくては!という短絡的な思考に走っちゃいけません。


まず「サービス管理ツール」を開いて次の二つのサービスを再起動してみてください。

サービス名表示名
UsoSvcOrchestrator Service の更新
wuauservWindows Update

すると、あらびっくり、これまで見えていなかった更新ファイルが急に見えるようになっちゃったりするのです。

(繰り返しますが、これは「オプションの品質更新プログラム」ではありません。)


そして、その見えていなかったファイルがいったん見えるようになりますと、Windows Updadeを介して更新できるようになります。

そして、更新すると、MoUsoCoreWorkerはおとなしくなり、以後はスリープを阻害することがなくなります。


私の経験では、これまで3回MoUsoCoreWorkerが出張ってきていたうち、3回ともこの方法で問題を解消できました。


以上、どなたか様の参考になれば幸いです。

ここまでお読みいただき、ありがとうございました。


2020年11月2日月曜日

Kingdom: New Landsをいただいたのでやってみた

Epic Gamesさんから頂戴しました。ありがとうございます。


私はせっかくのEpic Gamesさんからの頂戴物は貰いっぱなしで、そもそもインストールをする気になっただけでも椿事だったのに、面白かったのでびっくりしてしまい、思わず記事にしようと思い立った次第です。


このゲームの最大の特徴は「説明しない」という点に尽きます。

ゲームの勝利条件すら説明しません。

当然、ユニットの説明もありません。

たとえば、私の場合ではこんなことがありました。


森の中にある家にコインを払うと出てくるキャラにさらにコインを払うと馬に載せられることがわかって、載せて本拠地に帰還しましたが、下乗させる方法が分かりません。仕方がないので載せたままあちこち作業をしていましたが、ただ載っているだけでそのキャラがいったいどういう意味を持つのかがわかりませんでした。

やがて大規模なモンスターの襲撃を蒙りました。

その際に二列目の壁の後ろの最大限に強化してあった塔の前で、一列目の壁で巨大な怪物の襲撃に対処している兵の様子を見ていた時のことです。

塔の前に立つと、なぜかさらなる塔のアップグレードできることが分かったのでやってみたところ、さらにコインを要求する施設が出来上がりました。

さっそくコインを投入すると、その建造物にコイン一つにつき一つのナニかが設置されることが分かりました。

そうこうしているうちに第一列目の壁が敵に突破され、第二列目の壁での防御戦が始まりましたが、何が起きているのかわかりませんが、その建造物で生産されたナニかがどんどん消費され、いくらコインを投入しても片っ端から消費されてゆくという事態に陥りました。


その時は何とか二列目の壁で敵をしのぎ切ったため、その建造物が何らかの攻撃兵器だったのだろうと思っていましたが、どうも釈然としません。


実は、これはパン屋でした。

生産された「ナニか」というのはパンで、そのパンは乞食を引き寄せる効果はありますが攻撃能力はありません。

どんどん「ナニか」が消費されたのは、一列目の壁でモンスターに襲われて、力戦奮闘の甲斐なくも乞食となってしまった臣民が大勢でパンを食べていたからでした。


こういう類の一切を、説明なしで観察だけで理解し、活用せよ、というのが本ゲームの特徴です。

私は無理でした。どうしてもピンクのキャラが何だったのかが知りたかったので、情報を求めて検索してしまったからです。


もう一つ無理だったのが、6番目の島、スカルアイランドの勝利条件です。

船も修理できないため、これまでの勝利条件とは違うことは明らかですが、ではどうすればいいのかわからない。

1回目の上陸の時は、それを探るどころか、序盤に偵察のため奥地へ馬を走らせている中、私の判断ミスであっけなく王冠を奪われて成仏してしまいました。

2回目にスカルアイランドに上陸したとき、折角ここまで来てまた勝利条件探しからか始めなければならない、と思ってしまい、ガックリきてしまいました。

結局勝利条件を検索してしまいました。


すると、すべてのポータルを島中から同時に一掃すればよいということが分かりました。

同時にというのは、島の左右のもっとも外側に存在するポータルは一定期間で復活してしまうためです。


勝利条件が分かってしまえばもうこれまでの経験を総動員するだけです。

二度目の上陸の際、遠く離れたところに乞食のテントが配置される場合に備えてパン屋を、資金繰りに備えてユニコーンを連れてきていましたので、もうこれだけで勝ったようなものです。

とにかくユニコーンに草を食ませてコインをひりださせ、乞食を集めて弓兵にするだけの簡単な作業で終わるだろうと楽観視していました。

とはいえ、四つ目か五つ目のポータルを破壊したときのモンスターの報復攻撃で、城壁を相次いで突破された挙句に王国中央を超えて反対側の壁まで破壊され、騎士全員とほとんどの弓兵、工作兵も乞食化させてしまうミスを犯しました。

この際は、王もモンスターにどつかれまくって、ついには王冠が逃げる前方に吹っ飛ばされてしまうところまで追い詰められましたが、返す返すも本当に幸運なことに、馬上で落ちてくる王冠をキャッチでき、残余のモンスターも、塔に残っていた射手のおかげで撃退することができました。


まるであまりの惨状に復興など可能なのか、なんて思ってしまいそうな状況ですが、実際には、ユニコーンがひりだしたコインと、モンスターに襲われても破壊されないパン屋および銀行家のおかげであっという間にリカバリが完了してしまいました。

パン屋とユニコーンは縛らないと別ゲームです。


とはいえ、次のポータルを破壊した際の報復はもっと激しさを増すわけですから、このままでは次回は支えることは困難な状況です。

こうなった原因は、偵察時に初めて見た砂時計の像(後から調べてあれが砂時計と知ったのですが)がとても重要なものだと思い込み、その像を確保するようにポータルの破壊を進めていたのですが、実際には砂時計の像は無視してかまわないものでした。

確かに砂時計の砂が尽きればゲームオーバーとなるのだそうですが、それは冬が訪れた先の事だそうです。


優先して確保すべきなのは弓の像とハンマーの像でした。

今回の島では、その二つの像は、砂時計の像の反対側の第二ポータルの先に配置されていました。

そのため、アクセスが困難で、これまでずっとお布施に行っていなかったために、今回の襲撃前も惰性でお布施しなかったから起きた、起こるべくして起きたミスでした。


前の島から連れてきた騎士もいなくなったため、片側4名いた騎士が2名に半減してしまいました。

初めての挑戦ですから、仮に最後の島だから最後のポータルの破壊時に特別な敵が出てきて2名の騎士では歯が立たなかもしれない、などという懸念も浮かびましたが、もしそうなら現状の保有戦力ではこの島のクリアは不可能です。

従って、もう取り返しはつきませんから、片側2名の騎士でポータルを早いうちに破壊することのほかにやることはもうありません。

今回はさっそくその二つの像にお布施を行い、さっそく残る小ポータルを破壊し、敵の報復攻撃を迎えましたが、お布施の効果は絶大で、犠牲皆無で撃退できました。


撃退直後はもう、両方の壁から十分にコインを持たせた騎士をそれぞれポータルの破壊に送り込むだけです。


最終決戦はどんなものかと思って左側担当の騎士隊についていったのですが、別にポータルから特殊な敵が出てくるわけでもなく、淡々と破壊が進み、あっけなくスカルアイランドをクリアできました。


とにかくこのゲームは「ルールを知ること」なんだということがつくづくわかりました。


Steamではまずこのタイトルにお目に掛かれなかったでしょう。

Humble Bundleでバンドルされていてもまず興味を示さないと思います。

Epic Gamesでいただいて、しかも貰いっ放しな中、聞いたこともないタイトルなのにインストールしてプレイして、さらに面白かったということがあるなんて思いにもよりませんでした。

不思議な因縁を感じたので、チラシの裏ながらつづった次第です。


以上、ここまでお読みいただいてありがとうございました。

2019年4月28日日曜日

ffplay+ffmpegでその場で二つの動画の右半分と左半分を同時に再生する方法

この記事では、エンコード前の動画とエンコード済みの動画の画質の差や、同一の動画を違う形式でエンコードしたときの画質の差を、それぞれの動画を単純に左右に並べるのではなく、動画を右半分と左半分に分割して比較したい場合を想定しています。
ほら、テレビショッピングとかでよくあるじゃないですか。
同じ人の顔を画面上で半分に割って、左半分はナントカクリームを塗らなかった場合、右半分はナントカクリームでお肌ツヤツヤってやつを見せるアレ。
ああいうイメージです。

さて、画質の差は結局のところ数値化などは意味がなくて、見ている本人が納得できるかできないか、という点に尽きると思います。

まず、最も簡単な比較方法は動画プレイヤーを二つ並べて再生することです。
が、同一シーンを同時比較するためには、神業のような再生ボタン押下処理が必要になります。神ならぬ身の上、凡人にはとてもできません。

また、もしできたとしても、元画像が1440x1080だったりFHDだったりした場合、素直に横に並べると大きすぎて位置合わせが難しかったりします。だからと言って普段見るはずのサイズでチェックしないと検査になってないので、縮小等リサイズして比較するのは避けたいところです。

ということで、表題の件のように、二つの動画の左半分と右半分を同時に再生して、すぐに官能検査してみようというのが今回の目論見です。

これを行うのに必要なプログラムはffmpegとffplayだけです。
ffplayはvlc playerでも代替できます。

まず結論として、コマンドライン一式をWindowsのバッチファイルとして作成すると以下になります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
@echo off
setlocal
set SRC1=%1
set SRC2=%2
 
if not defined SRC1 goto invalidargument
 
REM remove doublequotation
set SRC1=%~1
 
if "%SRC1%"=="/?" goto help
if /i "%SRC1%" equ "/h" goto help
if /i "%SRC1%" equ "/help" goto help
if "%SRC1%"=="-?" goto help
if /i "%SRC1%" equ "-h" goto help
if /i "%SRC1%" equ "-help" goto help
 
if not defined SRC2 goto invalidargument
 
REM remove doublequotation
set SRC2=%~2
 
if not exist "%SRC1%" (
  echo エラー: %SRC1%がありません。
  goto help
)
if not exist "%SRC2%" (
  echo エラー: %SRC2%がありません。
  goto help
)
 
REM オーバーレイ文字列用ファイル名.拡張子抽出
set SRC1FNAME=%~nx1
set SRC2FNAME=%~nx2
REM 念のためアポストロフィを除去
set SRC1FNAME=%SRC1FNAME:'=%
set SRC2FNAME=%SRC2FNAME:'=%
 
REM 時間指定パラメタの記述場所判定用拡張子抽出
set SRC1EXT=%~x1
set SRC2EXT=%~x2
 
set STARTTIME=%~3
set ENDTIME=%~4
if defined STARTTIME ( set STARTTIME= -ss %STARTTIME% )
if defined ENDTIME ( set ENDTIME= -to %ENDTIME% )
 
set FFMPEG=ffmpeg.exe
set FFPLAY=ffplay.exe
set FFPROBE=ffprobe.exe
 
REM ぢでじ用パラメータ
set ASPECT=16:9
set MOVIE_WIDTH=1440
set MOVIE_HEIGHT=1080
set FPS=29.97
set CENTERLINE_WIDTH=2
 
if exist "%FFPROBE%" call :trygetparams
 
REM ファイル名表示用フォントファイル(要エスケープ: コロン及び¥)
set FONT=C\\:/WINDOWS/fonts/meiryob.ttc
REM 長いファイル名対策のため左右にテキストを流す
set DRAWTEXT_FNAME_OPT=fontfile=%FONT%:fontsize=24:fontcolor=darkgreen:shadowx=1:shadowy=1:x=w-mod(n*4\,w+tw):y=h-th-24:
REM 再生中動画のPTSとフレーム番号
set DRAWTEXT_PTS_OPT=fontfile=%FONT%:fontsize=12:fontcolor=white:shadowx=1:shadowy=1:text= pts\\:%%{pts\\:hms} %%{pts\\:flt} frame\\:%%{frame_num}
 
 
REM 再生開始及び終了時間指定
set DURATION1= %STARTTIME% %ENDTIME%
set DURATION2= %DURATION1%
REM (ffmpegではmpeg2tsは前置指定での時間指定不可なので引数の位置を後置する)
set DURATION_POSITION=PRE
if /i "%SRC1EXT%" equ ".ts" set DURATION_POSITION=POST
if /i "%SRC2EXT%" equ ".ts" set DURATION_POSITION=POST
if %DURATION_POSITION%==POST (
  set DURATION_POST=%DURATION1%
  set DURATION1=
  set DURATION2=
  echo  *警告: mpeg2tsのため指定時刻への頭出しに馬鹿みたいに時間がかかります*
  pause
)
 
set /A HALF_WIDTH=%MOVIE_WIDTH%/2
set /A RIGHT_HALF_X=%HALF_WIDTH%+%CENTERLINE_WIDTH%
 
set FILTER_OPT=^
    nullsrc=size=%MOVIE_WIDTH%x%MOVIE_HEIGHT%,fps=%FPS% [canvas]; ^
    [0:v] crop=%HALF_WIDTH%:%MOVIE_HEIGHT%:0:0,fps=%FPS%, ^
          drawtext=%DRAWTEXT_PTS_OPT% , ^
          drawtext=%DRAWTEXT_FNAME_OPT%:text=%SRC1FNAME% [left]; ^
    [1:v] crop=%HALF_WIDTH%:%MOVIE_HEIGHT%:%HALF_WIDTH%:0,fps=%FPS%,^
          drawtext=%DRAWTEXT_PTS_OPT% , ^
          drawtext=%DRAWTEXT_FNAME_OPT%:text=%SRC2FNAME% [right]; ^
    [canvas][left] overlay=x=0:shortest=1 [lefthalf]; ^
    [lefthalf][right] overlay=x=%RIGHT_HALF_X%:shortest=1
 
%FFMPEG% %DURATION1% -i "%SRC1%" %DURATION2% -i "%SRC2%" ^
 -filter_complex "%FILTER_OPT%" -f nut ^
 -aspect %ASPECT% -c:a copy -c:v rawvideo %DURATION_POST% pipe:1 ^
 | %FFPLAY% -i pipe:0 -fflags nobuffer
REM | %FFPLAY% -i pipe:0 -fflags nobuffer
REM VLCの場合は、「 | vlc.exe -」
goto end
 
:trygetparams
REM ffprobeの出力からfilter_complexの各値の取得を試みる
set FFPROBEOPT=%FFPROBE% -i "%SRC1%" -of csv -show_streams -hide_banner
REM ffprobeの結果をcsv形式で受け取り、カンマで分割した10,11,16,28の要素を取得
REM ※ここで直接リダイレクト先とパイプを指定しないとうまくいかないようだ
REM ※おまけにexeのパス名にスペースが入っていてもまともに動かないと来た。
for /f "usebackq tokens=10,11,16,28 delims=," %%a in (`%FFPROBEOPT% 2^>NUL ^| findstr video`) do (
  set MOVIE_WIDTH=%%a
  set MOVIE_HEIGHT=%%b
  set ASPECT=%%c
  set FPS=%%d
)
 
echo   ffprobe結果;
echo     size=%MOVIE_WIDTH%x%MOVIE_HEIGHT%
echo     aspect=%ASPECT%
echo     fps=%FPS%
pause
exit /b
 
:invalidargument
echo エラー: 引数が不足しています
:help
echo 使い方: %0 左半分を表示する動画 右半分を表示する動画 [ 再生開始時刻 [ 再生終了時刻 ] ]
echo         再生開始・終了時刻書式 HH:MM:SS または 秒
:end
endlocal
上記の内容を"左右2分割.bat"とでも名前を付けて保存して実行してください。使い方が表示されます。
ffmpegの特徴は複雑なことができる代償として呪文のような意味不明なコマンドラインを構築しなければならないところですが、今回も例にもれず一見意味不明な呪文が並びます。
おまけに当方の環境の都合で(サーバにはAV機能が皆無なので)Windows用のバッチとしたため、シェルスクリプトに比べて極端にひねくれています。
この両者の強力な組み合わせによって、上記のバッチは心の底からうんざりさせてくれるに十二分の威力を備えています。

さて、バッチの書式とか細かいことは放っておいて、重要なのは画像をそれぞれ左半分だけ、右半分だけ、それぞれ切り出して一枚の画像にすることですが、それをffmpegの -filter_complexオプションで行います。
このパラメータはffmpegの中でも極端に面倒くさいので、冗長になることを恐れずに説明したいと思います。

なお、行末の^(サーカムフレックス)はWindowsのcmd.exeで1行で記述しなければならない行を複数行に分割する記号ですので無視してください。
  1. 88行目のnullsrc=ですが、ffmpegが予め用意している多くの入力ソースの中の一つです。ここではこの上に2枚の動画を重ねてゆくベース動画として利用します。
    パラメータはsizeとfpsを指定しています。
    このバッチではsizeは最終的に出力される動画サイズ(1440x1080)、fpsは29.97が指定されています。これらの値はエンコード元が地デジのtsと仮定しています。ことさらにfpsを指定しているのはffmpegは無指定だと25fpsとして処理するからです。
    そして、このnullsrcから入力して加工(sizeとfps)した動画に対して[canvas]と名付けました。これの名づけルールは自由です。
    ここまででベース動画に対する定義は終わりました。続きがあるためセミコロンをつけます。
  2. 89行目の[0:v]ですが、これは1つ目の入力ソース(動画ファイル)コンテナ中で最初に見つかった動画を表しています。これを名付けたのはffmpegです。これに対してcropとfpsとdrawtextの指定をしています。
    cropは切り抜き範囲を指定します。このパラメータはffmpegのバージョンによって解釈される意味合いが変わるというとんでもない代物なので要注意です。
    バージョン20190426-f857753では切り抜き幅:同高さ:元動画に対する切り抜き開始位置X:同Yの順で解釈されます。
    上記のバッチでは720:1080:0:0として左半分を切り抜いています。言い換えると、1つ目の入力ソースの座標(左から0,上から0)から(幅720,高さ1080)だけ切り抜け、という意味合いになります。
    drawtextパラメータはどちらのファイルを切り抜いたかわかるようにファイル名を動画にオーバーレイするためのものです。
    以上を[left]と名付けました。これも名づけルールは自由です。続きがあるためセミコロンをつけます。
  3. 92行目の[1:v]ですが、これは2つ目の入力ソース(動画ファイル)中で最初に見つかった動画を表しています。これを名付けたのはffmpegです。これに対してもcropとfpsとdrawtextの指定をしています。
    異なるのは切り抜き位置で、上記のバッチでは720:1080:720:0を指定して右半分を切り抜いています。2つ目の入力ソースの座標(左から720,上から0)から(幅720,高さ1080)だけ切り抜けという意味合いになります。
    以上を[right]と名付けました。これも名づけルールは自由です。続きがあるためセミコロンをつけます。
  4. 95行目の[canvas][left]ですが、これは私がつけた名前です。この二つを重ね合わせるため、overlay=x=0:shortest=1というパラメータを指定しています。重ねる順番は左から順に重なります。この例では[canvas]の上に[left]が重なります。
    x=0は[left]を[canvas]上のどこに重ねるのかを指定しています。この場合は重ね合わせのx座標を0、つまり一番左としています。本来はこの記述は不要ですが、次の手順で右側に重ね合わせる際の座標指定との対比を分かりやすくするために付与しています。
    shortest=1はどちらかの動画の再生が終わったら処理を完了するというおまじないです。[canvas]の動画はnullsrc由来でdurationを指定していないので無限に続きますので、[left]の再生が終わったら完了するという意味になります。
    以上を[lefthalf]と名付けました。これも名づけルールは自由です。続きがあるためセミコロンをつけます。
  5. 96行目の[lefthalf][right]ですが、これは私がつけた名前です。この二つを重ね合わせるため、 overlay=x=%RIGHT_HALF_X%:shortest=1というパラメータを指定しています。重ねる順番は左から順に重なります。この例では[lefthalf]の上に[right]が重なります。
    x座標に指定している %RIGHT_HALF_X% の値は722ですので、2ピクセル分(本バッチの環境変数"CENTERLINE_WIDTH=2"として定義しています)だけ右にずれて重ね合わされます。これによって、隙間に[canvas]の地の動画が出ます(緑単色)。これは、左右の動画がどこで分割されているのかを分かりやすくするためにあえて行っています。
    以上でベース動画に右半分と左半分をオーバーレイ出来ましたので続きはありませんのでセミコロンをつけません
    なお、ここでセミコロンをつけますとffmpeg様に激烈に叱られた挙句ABENDしてくださいます。
というようなことをやった挙句、ようやく--filter_complex=オプションにダブルクォーテーションで囲んで指定します。

ここまでで2つの入力ソース(動画ファイル)が合成されているので、これをどこかに吐き出さないと人間様には見えません。
今回はいったんファイル化するのではなく、いきなり再生してしまおうというのが趣旨ですので、ffmpegにもれなくついてくるffplayで直接再生させたいと思います。

そのためのオプションは
-f nut -aspect %ASPECT% -c:a copy -c:v rawvideo pipe:1 | %FFPLAY% -i pipe:0 -fflags nobuffer
となります。

出力フォーマットにnut, ソースのサイズは1440x1080なのでぢでじのアスペクト比16:9を明示的に指定して、音声は再変換せずコピーして動画のコーデックをrawvideoとしてパイプ経由でffplayに出力しています。
vlc playerで再生したい場合は、パイプでつなぐアプリをffplayからvlc -(ハイフン)に置き換えてください。こちらもstdinから読み込んで再生してくれます。
率直に言ってffplayはとても使いづらいので、普段ffplayで動画を見ている人というのも少ないでしょうし、vlcも多くのOSに移植されていますから、vlcで官能試験を行ったほうが普段の視聴環境により近いかもしれません。

出力フォーマットのnutというのは単純にピクセルの羅列を扱えますので、rawvideoな動画を扱う際のフォーマットとして優れています。お望みであればこれをファイルに保存してもいいのですが、大変愉快なファイルサイズになります。

蛇足ですが、上記のバッチの例をお読みになれば上下分割や四分割なんかも簡単にできることはご理解いただけると思いますので、見やすいように改造してみてください。

なお、入力ソース次第では-ssが効かない場合があるとか使用するffmepgのバージョンが違うので挙動が違うとかザラです。
文中にもありますが、本稿は20190426-f857753を対象に記事を書いています。

個人的にはffmpegって強力で頼もしいけど融通は利かないしコロコロ仕様が変わるんで尊敬はするけど近づきたくはないです。

以上、大変くだらない記事で恐縮ですが、ここまでお読みいただいてありがとうございました。

以下、駄文です。
なんでこんなことをしようと思ったのかというと、HandBrakeのバージョンが上がるたびに同じH.265のエンコードパラメータを与えても妙に平均ビットレートが上がってきていて、同じCRF値でも1タモリ倶楽部単位(エンコネタではタモリ倶楽部1話分を当blogの基本単位とさせていただいております)の保存ファイルサイズが100MBほど大きくなってきたのが発端です。

なぜそうなるのかはHanbBrakeのせいなのか、libx265のせいなのかはわかりませんが、同一CRF値を指定してもエンコードされたファイルの平均ビットレートが上がっているのでファイルサイズが大きくなっているのが原因なのはわかったので、そっちが同じパラメータでも挙動を変えようって魂胆なら、こっちはもうCRF値を下げちまえ、もともとCRF値は28という(劣化に厳しい諸兄にはありえない)数値でエンコードしていましたが、今回は大台の30にして比較してみよう、でも画質はどうなるのかな?という素朴な疑問を持ったため、尊敬はするけど近寄りたくないffmpeg様のお力を拝借することにした次第です。

やってみてわかったことは、H.265の低ビットレートにおける再現力の高さです。
確かにわずかに28と30では違うかもしれないが、そもそもいずれもオリジナルのtsとの差ともわずかだ、という官能評価に至りました。
ぶっちゃけ、個人的評価ですがエンコ元先を左右に並べても上下に並べてもいずれも全然気にならないことが確認できました。

HEVC、恐るべし。そんなことをつらつら思う平成最後の日曜日でございます。
駄文までお読みいただき、誠にありがとうございました。