P720 (Xeon Silver 4114 * Quadro P400) を半年以上使ってのインプレッション

ざっくり印象

基本的には「あまりよくはないが不満もない」というのが印象である。

  • 体感的には速くない。実際処理時間は劇的には速くなっていない
  • だが、従来のものと比べると随所で性能差を感じる
  • 多プロセスを走らせたときでもすごく速いとは感じない。1プロセスごとに結構時間がかかるので、量を消化したいときは厳しめ
  • コンシュマーCPUと比べて優れているのかどうかはだいぶ怪しい
  • 「速くはないけど余裕はある」という不思議な挙動。フルロードでもCPUに空きがなくて処理ができないというようなことは起きない
  • ファンの回転数があまり上がらず、結構静か
  • 安定性があまりない。特にフロントUSBデバイスがごく限られた条件でした機能しないのが結構痛い
  • 再起動したときにUSBデバイスが使えなくなったり、よくわからない不具合がとても多い
  • HTTはまったくいらない。フルロードしているとき、きっかり50%になる
  • 重量はとても重いけれど、取手があるためそれほど取り回しはきつくない
  • インパクトはそれなりにある。現状、7980XEでも18コアなので、20コア40スレッドというのは「桁違い」と捉えてもらえる。しかし、2990WXが32コアであることから、「圧倒的」という感覚は相当薄れている
  • Windows 7が動く最終機という意味合いがあったため、Windows 7でASIOが動作しなかったのは致命的だった
  • 内部がhpほど整理されておらず、電源パーツなどが不足しているため拡張性はあまり高くない
  • 「良い」とはあまり思ってないけれどあまり不満はなくてそこそこ満足している

つまりコレ自体に不満はそれほどないのだが、値段的に40万円を越える程度であることから、ゲーミングPCと比べて2倍程度の価格的価値があるかというとちょっと難しい。

ただし長期運用を考えるとトラブルに対応しやすく、帯域的には拡張性が高いという点は評価できる。 ちゃんとWindows 7が動作していて、かつ拡張が楽な構造をしていたら性能の問題は「織り込み済み」だったので、なにも気にしなかったと思うのだけど…

拡張プランは延期

しかし、もともと「64GB RAM, GTX1080Ti, Xeon Gold 6138に換装」と予定されていたが、現在そのプランは延期、変更されている。

理由は、

  • 通常利用では有り余っているので強化の必要性が全くない
  • メモリを増やしてもプロセス数増加によるパフォーマンス増加がいまひとつ望めない。ディスク速度の問題もあり、それをやるならプログラム側に大改修が必要で、追いついていない
  • メモリが高い。DDR4 ECC Regメモリの高さは半端ない
  • QuadroのNVENCがそれなりの速度が出ること、画質を問題にするとNVENCならとても使っていられないことからNVENC目当てが成り立たなくなった
  • 「ゲームしようかなぁ」とか思っていたけれど、やろうとしているゲームがなくなってしまった
  • 引っ越さないことにはRCSはできない
  • まぁまぁ性能が良い割に消費電力が少ないというのにすっかりやられて、爆熱仕様にする気にならない (すでに十分熱いし)

Quadro P400はTDPが40Wとビデオカードとしては非常に消費電力が小さく、Xeon Silver 4114も85Wと控えめ。 加えて4114がコア数が多いため、「軽い処理が色々ある」という状況ではより省電力に動作することができる。 powersaveガバナーとの相性がよく、通常のデスクトップ使用で90-145Wと電力的に軽い。 これは多数のスクリプトを回していてもあまり変わらない。

TDP130Wのプロセッサを使うZ400では120-190Wとひとまわり多く電気を使う。恐らくCore XクラスのCPUでも同じような事情だろう。 TDP95WのA10-7870Kは80-140Wといったところ。性能の割にかなり電気を使う、という印象だが、それでも消費電力は少なめだ。

「性能が高い割には普通に使っていればエコで、いざとなれば高性能」というのはなかなか魅力的だ。 ただ、デュアルソケットなので素の状態でも割と消費電力は高く、ピーク性能があまりないため、Core i7と比べて良いのか、というと難しい話になってくる。 Core i7マシンでこのような細かい測定をすることがないためわからないのだが、Core i7のほうが全方位に渡って良い、という可能性は普通にある。

Xeon Gold 6138は1機30万円ほどするのだが、比較可能なベンチマークとしてはOpenSSL Signが2500を越える程度であるのに対し、Ryzen Threadripper 2990WXが5862に達している。

なお、Passmarkスコアはまるで伸びず、23927点にとどまる。 これはInterger Maths, Floating Point Mathは7980XEにダブルスコアをつける一方、Prime Number, PhysicsはRyzen 7 2700と同等以下、ということでこのスコアになっているらしい。

Cinebench R15ではXeon Gold 6138が3069点、Ryzen Threadripper 2990WXが5267点。

つまり、性能的にはXeon Gold 6138と比べても2990WXは「下手すれば倍」という性能である。 CPUを2機積んでも「倍」にはなかなかならないので、Xeon Goldに換装しても2990WXに届かない可能性は高い。

そしてお値段が、GELLERIA TRZ(2990WX + GTX1080Ti)が60万円、V-SPECではGTX1060と組み合わせて50万円、サイコムはGT710と組み合わせて42万円、2x GTX1080 SLIで60万円といったもので、「Xeon Goldへの換装をするくらいなら2990WXマシンを追加するほうが良い」という判断が働いている。

消費電力の比較

まずはP720のスペック。スピーカーやディスプレイなどのパワードデバイス、キーボードとマウスは含めていない。

P720
パーツ 使用部品
CPU 2x Intel Xeon Bronze 4114
メモリ DDR4 ECC Registered 16GB
ビデオカード Nvidia Quadro P400
ディスク NVMe SSD, SATA3 SSD, SATA3 2.5" HDD 5400rpm, SATA3 2.5" HDD 5400rpm
NIC Intel GbE(l219-LM), Intel GbE(l210)
その他 デバイス NI Audio4 DJ, TASCAM US-366
電源 900W Gold

比較対象は2015年のエントリーグレードのPCであるAMD A10-7870K (Godavari) APU搭載マシンである。

A10
パーツ 使用部品
APU AMD A10-7870K
メモリ DDR3 32GB
ビデオカード APU内蔵
ディスク SATA2 SSD, SATA2 3.5" HDD 5400rpm
NIC Atheos GbE
その他 デバイス
電源 750W Bronze

もう一台は先代メインマシンであるhp Z400 Workstation。 2010年のメインストリームワークステーションで、性能的にはA10とあまり変わらない(若干良い程度)。 CPUはXeon W3565()

Z400
パーツ 使用部品
CPU Intel Xeon W3565
メモリ DDR3 ECC Unbuffered 24GB
ビデオカード Nvidia Quadro 2000
ディスク SATA3 SSD, SATA3 2.5" HDD 5400rpm
NIC Broadcom GbE
その他 デバイス SATA3 DVD Multi
電源 500W

実際の計測。 P720についてはデフォルトの電力プランがpowersaveで、performanceとの差が大きいため、起動後についてはperformance時のものも記載する。

消費電力(W)
条件 P720 P720 Performance A10 Z400
電源投入時 132 70 128
Grub起動時 125 148 127
Grub LUKS 耐機中 132 167 134
ログイン アイドル 76 48 84
Cinnamon アイドル 70 71 50 121
Firefox起動中 101-126 131-140 86-117 147-175
GPU Test (FurMark) 110 93-135 93 133-146
フルロード 193 192 168 219

ManjaroはGrubでLUKSを解除する仕組みだが、このときパスフレーズを入力せずに放置すると果てしなく電力を使う、ということが分かっている。

フルロードは動画ファイルをxz -t 0 -zce > /dev/nullをコア数行うという方法で試している。 CPUとGPUの両方をフルロードにするテストは、マシンへの負荷や温度的な理由からしていない。

参考として、STH(Server The Home)でXeon Gold 6138の消費電力が示されており、

  • Idle: 75W
  • 70% Load: 203W
  • 100% Load: 232W
  • Peak: 241W

とのことである。(208Vの電源を使用) 4114と比べるとだいたい倍ぐらい、という感じだろうか。STHでは4114について、最大で101Wに到達したことが書かれている。

Akiba PCの記事では Core i7-6700Kの高負荷時システム電力が128.1Wとあり、6950Xで175.1Wとのことだ。

また、Core i7-8700Kユーザーの報告で、アイドル時21W、高負荷時135Wが報告されている。

もう少し詳しい話として見るとマイナビニュースで8700Kや1800Xの計測がされていて、これを見ると80-220Wという感じだ。ちなみに、これはGTX1080を載せているらしい。

やはりメインストリームワークステーションのZ400はP720よりも一回り消費電力が大きい。 また、Z400は消費電力が上がりやすく、実用しているとだいたい130W前後で動作する。P720は85W程度であるため、結構差が大きい。

さらに、Xeon W3565のTDPが135Wなのに220Wに達するのは「TDP越えてないか?」と大変心配になる。 Z400は水冷であり、冷却容量はそれなりに余裕があるので問題になっていないが、これはきつそう。

期待したほどではないが、基本的に余裕をもってP720は常に省電力である。 Xeon Gold 6138 2x + SLI GTX1080Tiというような構成も考えていた(これだけでTDPは750Wに達する)のだが、結局900W電源は過剰だったようだ。

総括

まず、前提となるのが、P720は「仕事用」である。 継続的に、効率的に仕事ができることが大切なのだ。

だから業務継続性においてのみ重要視したWindows 7が動作しなかったのは、選択理由をそもそもゆるがすようなもので厳しい。 ワークステーションのほうが動作が安定している、といった点を重視したのだが、この点もいまひとつでこれらの「P720が期待したように動作しない」という点がなにより不満をもたらしている。 これでコンシュマークラスには到底実現できないような性能であればまだ納得するのだが、単純な性能面ではあまりアドバンテージがないため、「単純に高かった」という印象になってしまう。

しかし、それを理由に公開したり残念に思えていないのは「特に不満はない」という点が大きい。

Windows 7は結局思ったように使えなかったが、KOMPLETE 9 ULTIMATEがWindows10に対応したこと、Sonar X3 Producerが「だいたい動いた」こと、SONARが廃止になって、それに備えてAbility 2.5 Proを導入したことなどから「Windows 10でも一通り使える」状態になった。 音楽制作系以外の環境と混在させることには不安もあったが、とりあえず問題は生じていないのでこのまま使っていけそうである。

現環境においてはいくつかの不具合(特にフロントパネルのUSB問題)があるが、Linuxで運用していて致命的なわけでもない。 Windows 10のほうでもASIOドライバをインストールするとフリーズするという問題があって血の気が引いたが、こちらはWindows Updateで解消した。

通常の利用では当然ながら性能が不足するということはない。 シングルスレッド性能が非常に低いため(A10よりちょっといいくらい、コンシュマープロセッサではPentium Goldよりずっと低い)動作快適性は微妙だったりするのだが、Linuxであれば変につっかえることもないし(Windowsだと起動後しばらくや、突然はじまるWindows Updateで使い物にならないほど止まる)、私の場合は多くのプロセスを動作させるためひょんなことで一時フリーズしたりしていたのだが、それもなくなって快適になった。

もちろんリソース総量的にコンシュマーCPUで足りる可能性もあるが。

拡張性に関してもコンシュマーCPUよりは有利なのは確かで、価格差をさておけば特にコンシュマーCPUのほうが良かった、という感じはない。 価格差を含めるとCore i9-7920X+GTX1080のゲーミングPCという選択肢があったため、性能面では残念な部分もなくはない。だが、Core i9-7920Xマシンとはかなりの性能差があることはわかりきっていたので、コンシュマーCPU比では性能ではなく可用性に料金を払ったと考えて良い。

Xeon 4114の性能はおおよそ「並列化すれば最終的には速い」というまんまのもので、使いこなしは難しい。 あるひとつのことを実行したときにかかる時間は「Celeronよりはマシ」という話でしかないため、これでは速さを感じることはできない。実際にはそこまで時間がかかる処理は並列化されていることが多いためまぁまぁ速く終わるのだが、なにもかもが一瞬という速さではない。 そのため、この性能を活かすにはなるべく同時に複数の処理をし続けて、「24時間あたりの処理量は多い」というような内容になる。 ざっくり「Celeron G3920マシンを5台用意すれば1台のCore i7マシンよりたくさんタスクを消化できる」というような話だと言えば難しさが伝わるだろうか。

Celeron G3920マシンを5台用意するよりはずっと省電力なので、効率は良い。だが、その性能を生かせなければ効率などあったものではない。 普通の人には到底お勧めできるものではない。

私は近年、“Orbit”と呼ぶデザインを採用している。 これは作業概念を小さなスクリプトにし、網羅的に処理するということをタスクスケジューラによって繰り返し行うものだ。 処理自体は軽いが並行で多数の処理が走り続ける。このデザイン自体はXeon 4114プロセッサと非常に相性がいい1。だが、軽い処理では4114プロセッサを使い切ることは到底できず、かといって重い処理(例えばffmpeg)はOrbitデザインに組み込めないほど時間がかかってしまう。 また、現状ではOrbitデザインで作られているスクリプトも最大で5スレッドしか生成しないため、性能を活かし切るにはより多くのスレッド(というよりも任意の数のスレッド)が生成できるデザインに変更する必要がある。 ただ、OrbitデザインはIOの比重が高いため、あまりシークに時間のかかるHDDには向いておらず、恐らくプロセッサ性能が向上しても効率はよくならない2

Xeon 4114の真価を発揮するのはこのスクリプト群を改良してからになるだろう3

最大の誤算は「Xeon Gold 6138の2台分に匹敵するトータルパワーと、Xeon Gold 6138と同等のコアパワーを備え、1ユニットで32ものコアを持ち4、我がP720と変わらない値段で搭載機が買える」Ryzen Threadripper 2990WXの登場である。 さすがにあれと比べると何もかもがどうしようもない。

だが、2990WXが誰にでも勧められるかというとそうでもなくて、まず性能は著しく過剰だし、性能を必要とするゲームにはあまり向いていないので、ゲームではない部分で非常に高い処理性能を必要としている人のみが適する、となかなかハードルは高い。2950Xのほうなら、ゲーマーを含めた高性能PCを必要とする人に勧められるのだが。

P720、というかXeon Scalable Processor Family搭載マシンについては何度か相談されているのだが、明確に用途が答えられない人にはとても勧められないし、「速い」ことを期待しているならそれも勧められない。 クリエイター系の人についても、コア性能が低くてレスポンスがあまりよくないので勧められない。実際このマシンでGimpやShotcutなんかを動かしていると決して快適ではないと感じる。 可用性とコアの数が重要になる場合だけ、お勧めできる。


  1. Xeon 4114プロセッサは「コア数優先、コア性能はすごく低い」というプロセッサである。Orbitデザインは多くの場合処理は軽いため性能が高くても活かすことができないが、条件によってはかなりの数のプロセスが発生するためこのようなプロセッサはうってつけである

  2. ちなみに、Orbitデザインは大量のプロセスを生成するがすぐ終わってしまうため、forkにかかるコストが大きくそもそも実行効率はよくない。だが、開発やメンテナンスは容易で柔軟性が高い。

  3. なお、PureBuilder Simplyも1.6のうちに並列化スクリプトが作られる予定になっている。

  4. 32コアというのは、Xeon 4114のデュアルよりも多いのである。

TD-4KPでDTXManiaはじめました (初心者向け記事)

DrumManiaとは

ドラムマニアはKONAMIが運営するリズムアーケードゲームである。

1999年に先に登場したGuiterFreaksとファミリーシリーズになっていて、セッションプレイも可能。 GuiterFreaksはターンテーブル風コントローラを持つリズムゲームのBEMANIシリーズの第4弾として登場した。

これまでのゲームがあくまで「ゲーム化されたもの」だったのに対し、DrumManiaはエレクトリックドラムのDTXシリーズを展開するヤマハがパッドを提供し、多少簡易化されたエレクトリックドラムの形状をしている。

2010年に登場したDrumMania XGシリーズからはクラッシュシンバル(従来はライドと共通だった)とフロアタム、レフトペダルが追加され一般的なドラムキットと同じ構成になった。 (ただし、レフトバスペダルとハイハットペダルは共通の扱いで、ハイハットの開閉状態は認識しない)

20年続く人気シリーズで、ドラム的にプレイすることもできる一方、ゲーマーがタイミングゲームとしてハイスコアを追求することもある。 ハイハットが非常に低くセットされていてクロスすると左手のスペースが狭いため、オープンハンドで叩くプレイヤーも多い。

DTXManiaとは

BEMANIシリーズは人気が高かったので、それを家庭でもしたいという要望は強かった。 家庭用ゲームとしても販売されていたが、PCでプレイしたいという要望、また家庭用ゲーム版が発売されなかったり、安定しなかったりしたこともあって類似ゲームが色々と作られた(BandJAM, BM98!!, DrumMIDI, DrumingTrainer, Perfect Beat, SessionStream, ドラムもんなど)。

DTXManiaは2000年に登場した、そのようなもののひとつ。

このようなものはドラムトレーニング用のアプリケーションでも存在する(例えばMelodicsとか)。 DTXManiaはドラムトレーニングアプリであり、またDrumManiaクローンでもある。

現在もPCゲームとして遊べるDrumMania及びGuiterFreaksのクローンとしてプレイできる一方、 初期からの特徴としてハイハットのオープンクローズに対応しており、DrumManiaよりもリアルなドラムゲーム、あるいはドラムトレーニングアプリとして利用できる。

また、ドラムだけでなくキーボードやジョイスティックでも遊べる(なんなら音ゲーコントローラでも遊べる)し、パッドシャッフル機能もあるのでより「音ゲー的に」遊ぶこともできる。ビートマニアのコントローラやDDRのコントローラでも遊べる。

導入・選択

基本的なバージョンは次の通り

DTXMania
本家。バージョン112が2018年3月リリース。 基本的に旧ドラムマニアベースでLPがない DTXManiaXG Ver.K
現在の主流。 DrumMania(XG/Gitadora)に寄せてあり、5レーンのGuiterRevolutionXG Ver.Kもある。 DTXMania Matixx
Gitadora Matixxそっくりの新しいバージョン。本家の作者によるもの。 今のところ機能は最小限。

本家とXG Ver.Kに関して大きな違いとなるのが、LP(左ペダル)だ。

譜面上はLP(ハイハットペダル)とLBD(左バスペダル)があるが、 DTXManiaには独立したLPがなく、自動的にバスドラムとオープンハイハットに振り分けられるようになっている。

XGのほうはLP/LBDを扱えるようになっていて、LBDGraphicsという設定でこのふたつを分けて表示するかどうかを選べる。

DTXMania Matixxのほうはゲームセンター準拠のためLBDもLPもLPという仕様。

DTXManiaおよびXG var.Kは特にインストールも必要のないスタンドアロンアプリ。 Matixxはインストールするタイプで、Windows 10のみ。

だいたい譜面はLPを持っているのでDTXManiaXG Ver.Kが主流のようだ。 こちらは採用されている画面デザインによって色々バージョンがあるが、これはDrumManiaのどのバージョンのデザインに似せているかの違いだ。

V-Drums TD-4KP をつなぐ

TD-4KPは初代V-Drums portableで持ち運べるフォールディングタイプのV-Drums Kitだ。

音源モジュールはTD-4。発売は2009年と結構古い。 V-Drums Portableシリーズは2014年発売のエントリーモジュール TD-1を採用したTD-1KPX2に移行している。 こちらはモジュール自体はTD-4より簡素なものだけれど、パッドはメッシュヘッドになっていてグレードが高いし、ツインペダルに対応している。

TD-4モジュールは古いので、USB端子がなく、MIDI端子を持っている。 これを簡単と見るべきか扱いにくいと見るべきかは難しいところだけれど、とりあえず最近のオーディオインターフェイスはMIDI端子を持っていないのでめんどくさいのはまちがいない。

私は推奨されているRoland UM-ONEを使用した。これはシンプルなUSB-MIDIアダプタで、MIDI-INとMIDI-OUTを持っている。

手順は次のとおりだ

  • UM-ONEのスイッチをCOMPにする
  • 付属ディスクからドライバーをインストールする
  • USBを接続する
  • CONNECT TO MIDI OUTを TD-4のMIDI OUT端子に接続する

注意点は次のとおり

  • 先に接続するとデフォルトドライバがインストールされる。純正ドライバをインストールしようとすると、これを削除して再起動するという手間が加わるし、接続しているとインストールできない
  • UM-ONEの端子は “MIDI IN” ではなく “CONNECT TO MIDI OUT” と書かれている

これで使えるようになった。

DTXManiaXG Ver.Kの設定をTD-4KPに合わせる

パッドの設定

まずはDTXManiaを起動する前にTD-4本体からMENU->6. MIDIとしよう。 これで叩いたときにどのイベントが発生するかを確認できる。

セレクトスイッチを使ってチャンネルを変更することもできる。必要なら変更しておく。 再起動時にチャンネルが変わってしまって認識されないこともある。

DTXManiaXGを起動し、Configuration -> Drums -> Drums Keys から各ノーツにパッドを当てていく。 同じイベントを複数のノーツにあてることはできない。

TD-4KPの場合シンバル全てEdgeとBowのふたつのイベントを発生する(CY-12R/C, CY-13R, CT-15Rに換装している人はベルも)。 ハイハットはオープンとクローズで異なるイベントを発生するが、TD-4は多分ハーフオープンイベントは生じない(そもそもFD-8でハーフオープンを鳴らすのはとてもむずかしい)のでハーフオープン処理は多分いらない。

メッシュスネア(PDX)を使っている場合はリムイベントもある。リムイベントを当てるかどうかはお好みだけど、私の感覚としては「クロススティックはわざわざやるから鳴ってほしいけれど、オープンリムショットはミスでやることが多いから切りたい。でもTD-4はそもそもオープンリムショットを認識しないので両方スネアにあてておけばいい」だ。

表示と鳴り方の設定

HH-Group

次のようになっている

  • HH-0 LC|HHC|HHO
  • HH-1 LC & (HHC|HHO)
  • HH-2 LC | (HHC&HHO)
  • HH-3 LC & HHC & HHO

TD-4KPには左シンバルがあり、ハイハットペダルもあるのでHH-3でよさそうなのだけれど、 FD-8の離れがすっごく悪くて、ペダルハイハットとオープンハイハットが交互に出てくるフレーズはまず間違いなく成功しない。 TD-4上で離れていても、ペダルオフの信号をすぐ出してくれない。

なのでHH-2 (ゲーセンと同じ) にしておく必要がある。 本当はHH-3でがんばりたいのだけど。

BD-Group / LBDGraphics

TD-4KPには「左バスペダル」はないので、全て区別されるBD-0はなし。 また、ツインペダルにも対応していないのでBDとLBDを同一に扱っても右足で連打するしかない。

そのためゲーセンと同じ仕様で「LPはバスとハイハットのマージ」として扱えるLP & LBD | BDであるBD-2。 バスの左右の区別をやめてほしいならDB-3

BD-2にするならLBDGraphicsAでよく、BD-3の場合はLBDGraphicsBにしたほうが練習になる。

CY-Group / Cymbal Free

TD-4KPには「右シンバル」はないので、ライドと同一視してくれるCY-1(ゲーセンと同じ)か、 Cymbal Freeを有効にしてシンバルはクラッシュを叩く。

なお、CY-1にしとかないと、シンバルふたつ同時鳴らしのときに困るかもしれない。

また、NumOfLanesB(9レーン)にするとゲーセンと同じで右シンバルとライドシンバルをマージしてくれる。 これも解決策になる。違うレーンで叩くところは同じっていうのは割と混乱するので、お勧めかもしれない。

HHO Graphics

Cにすればゲーセンと同じ仕様。

しかし、いくらペダル切れが悪いと思っても、同一視していてもオープンとクローズはたたきわけたいだろう? というわけで、DTXMania的にはA

接続とHit Sound

基本的には

  • Hit Sound ONでPCから音を聞く
  • Hit Sound OffでPCとTD-4のAudio inをつなぎ、TD-4で音を聞く

の2択なのだけど、後者はLPで混乱するし、TD-4の音はしょぼいのでおすすめできない。

ちなみに、私はTD-4で音を聴いているけれど、Hit Sound ONにしている。

Velocity

Ver.Kの場合はconfig.iniの編集。

TD-4KPはケーブルに干渉したり、共振でもスイッチが入ってしまうので、若干制限したほうがよさそうだ。 タイコは20、シンバルは5だろうか。 私はケースに触れてしまうことがあるため、ハイタムを高めに制限しているが。

SoundType

Windows Vista以降ならWASAPI。

ASIOはうちの場合できる環境だけど(音楽制作用なので)、めんどい。

音ズレ

Input Adjustで調整できるけれど、環境によるので、あまりこれといった設定はなく、 それ以上に「譜面によってずれ方が違う」ほうが大きい。

これはShift+↑↓で10ms単位、Ctrl+Shift+↑↓で1ms単位で調整でき、曲ごとにこの調整は保存されるというので、 主にこちらを使うことになりそう。

これで調整したら、違う環境ではInput Adjustで全体を合わせればよさそう。

所感

TD-4KP叩きにくい

「コンパクトであること」を最優先した結果なので仕方ないけれど、セッティングの自由度が低く、パッドは小さく返りも悪いことから結構叩きづらい。 叩いているとフロアタムは遠くにいってしまうし、シンバルは回ってしまうし、やりづらい。

以前はバスペダルが非常に悪くて苦労したが、現在はアイロンコブラのまぁまぁ良いものにかわったため叩きやすくなった。

楽しい

単にTD-4KPで基礎練しているよりも楽しいし、曲練習のいいサポートになる。 単純にスコアを叩いているだけだとあまり効果はないだろうけれど、 特にHit Soundをオフにしていれば表現力もチェックできるため、曲に合わせた練習をしつつ立てタイミングに点数をつけてもらうことができる。

どちらかといえば、自分がやりたい課題曲の譜面を作ってやり込むのがいいと思う。

これTD-17KVXでやったら相当楽しいだろう。 反応は良好で、DTXManiaのフル機能が使えるし、 フィーリングもDrumManiaより格段によく、ちゃんと叩きやすいセッティングで叩くことができるのだから。

時間泥棒

普通に練習していても2時間くらいは経つが、逆にゲーセンでは2時間は割と長いほうだ。 もちろん、お金がかかるという面もあるが、そもそも「3曲+アンコール」という構成であることと、プレイ数が限られていること、見ている人がいる場合あまりに簡単な曲をやることは気が引けるといった理由から激しい曲をプレイする傾向があり、特にアンコールではきつい曲をやるため長時間はもたない。

DTXManiaではいくらでも同じ曲を練習できるため、長時間になりやすい。

なお、DrumManiaは1プレイ120円で、2時間で1500円くらい。 毎日やるならPCとエレクトリックドラムを揃えるところからはじめても半年くらいで元が取れる。

なお安いエレクトリックドラムはDTX400KS, TD-1K, が5万円ほど、Surge Mesh Kit1が7万円ほど、私お気に入りのTD-17KVX-Sは16万円ほどだ。

楽譜がわりになるのでは

ドラムは他の楽器と比べて楽譜を設置することが難しく、楽譜の重要性も低いためより暗譜よりである。

そのため、新しい曲はだいたい覚えて叩くのだが、譜面を作るときにDTXmaniaとかありだと思う。

私がやるとドラムで譜面を作っても自分のレベルより相当低い譜面しか作れない。 DTXManiaの譜面作成ならいくらでも難しい譜面を作ることができ、それを練習してから臨めばハイレベルな演奏ができる気がする。

ちょっと不安定

DrumManiaでもプチフリーズによる「飛び」が発生することがあるが、それと比べてDTXManiaはやや飛びやすい。

そもそもDrumManiaはWindows Embedded Standard 7上で動作しており、それと比べて不利なのかもしれないが、 Celeron B810よりは高クロックなプロセッサで動かしているのでがんばって欲しい感じはある。

また、割と落ちる。

LPとLBD問題

DrumManiaの仕様上難しいのかもしれないが、まずLPとLBDがちゃんとわけてあるかという問題がある。

実際は左右どちらで入っても構わないため、現実的にはBD-3しかなくなってしまい、「LBDを全てBDに追いやる」というオプションが欲しい。


  1. 低価格ながら少し口径の大きいメッシュパッドを採用していると評判。表現力があまりないが、ゲームのトリガーとして使う場合は問題にならない。 ただ、故障が多いという噂もある。

ELECOM EX-G UltimateLaser MouseとLinux (未解決)

珍しく伝統的なLinux問題のお話をする。

私はELECOMのEX-G UltimateLaser Mouseを愛用している。

EX-Gシリーズは10個のボタンがあり、10番目はDPI変更ボタンになっているのだが、Ultimate Laser Mouseだけはファンクションボタンが3つある12ボタンマウスになっている。

せっかくなので、というか使いたい意図があって残り3つのボタンを使おうとしたのだが、 xevで見るとファンクションボタンが全部button 9になっている。 button 9は進むボタンに当てられていて、実際進むボタンとして機能する。

しかし、これでは困る。ドライバが間違っているのだろうか。 まずはデバイスがどう認識されているのか確認する。

I: Bus=0003 Vendor=056e Product=00d3 Version=0100
N: Name="ELECOM ELECOM UltimateLaser Mouse"
P: Phys=usb-0000:00:14.0-14.1/input0
S: Sysfs=/devices/pci0000:00/0000:00:14.0/usb1/1-14/1-14.1/1-14.1:1.0/0003:056E:00D3.0003/input/input4
U: Uniq=
H: Handlers=event4 mouse0 
B: PROP=0
B: EV=17
B: KEY=1f0000 0 0 0 0
B: REL=143
B: MSC=10
Bus 001 Device 010: ID 056e:00d3 Elecom Co., Ltd 
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0         8
  idVendor           0x056e Elecom Co., Ltd
  idProduct          0x00d3 
  bcdDevice            0.01
  iManufacturer           1 ELECOM
  iProduct                2 ELECOM UltimateLaser Mouse
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x003b
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      1 Boot Interface Subclass
      bInterfaceProtocol      2 Mouse
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.00
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      89
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval              10
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.00
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      46
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval              10
can't get debug descriptor: Resource temporarily unavailable
Device Status:     0x0000
  (Bus Powered)

うぅむ、正しく認識されているようだ。 ドライバはどうなっているのだろう。

[    16.960] (**) ELECOM ELECOM UltimateLaser Mouse: Applying InputClass "evdev pointer catchall"
[    16.960] (**) ELECOM ELECOM UltimateLaser Mouse: Applying InputClass "libinput pointer catchall"
[    16.960] (II) Using input driver 'libinput' for 'ELECOM ELECOM UltimateLaser Mouse'
[    16.960] (**) ELECOM ELECOM UltimateLaser Mouse: always reports core events
[    16.960] (**) Option "Device" "/dev/input/event4"
[    16.960] (**) Option "_source" "server/udev"
[    17.017] (II) event4  - ELECOM ELECOM UltimateLaser Mouse: is tagged by udev as: Mouse
[    17.017] (II) event4  - ELECOM ELECOM UltimateLaser Mouse: device is a pointer
[    17.017] (II) event4  - ELECOM ELECOM UltimateLaser Mouse: device removed
[    17.076] (**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:14.0/usb1/1-14/1-14.1/1-14.1:1.0/0003:056E:00D3.0003/input/input4/event4"
[    17.076] (II) XINPUT: Adding extended input device "ELECOM ELECOM UltimateLaser Mouse" (type: MOUSE, id 9)
[    17.077] (**) Option "AccelerationScheme" "none"
[    17.077] (**) ELECOM ELECOM UltimateLaser Mouse: (accel) selected scheme none/0
[    17.077] (**) ELECOM ELECOM UltimateLaser Mouse: (accel) acceleration factor: 2.000
[    17.077] (**) ELECOM ELECOM UltimateLaser Mouse: (accel) acceleration threshold: 4
[    17.134] (II) event4  - ELECOM ELECOM UltimateLaser Mouse: is tagged by udev as: Mouse
[    17.134] (II) event4  - ELECOM ELECOM UltimateLaser Mouse: device is a pointer
[    17.135] (II) config/udev: Adding input device ELECOM ELECOM UltimateLaser Mouse (/dev/input/mouse0)

Using input driver 'libinput' for 'ELECOM ELECOM UltimateLaser Mouse' …あぁ、そういえばManjaroはlibinputに移行していたなぁ…

⎡ Virtual core pointer                          id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ ELECOM ELECOM UltimateLaser Mouse         id=9    [slave  pointer  (2)]
⎣ Virtual core keyboard                         id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
    ↳ Power Button                              id=6    [slave  keyboard (3)]
    ↳ Power Button                              id=7    [slave  keyboard (3)]
    ↳ FCL USB Keyboard                          id=8    [slave  keyboard (3)]
Device 'ELECOM ELECOM UltimateLaser Mouse':
        Device Enabled (151):   1
        Coordinate Transformation Matrix (153): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
        libinput Natural Scrolling Enabled (288):       0
        libinput Natural Scrolling Enabled Default (289):       0
        libinput Scroll Methods Available (290):        0, 0, 1
        libinput Scroll Method Enabled (291):   0, 0, 0
        libinput Scroll Method Enabled Default (292):   0, 0, 0
        libinput Button Scrolling Button (293): 2
        libinput Button Scrolling Button Default (294): 2
        libinput Middle Emulation Enabled (295):        1
        libinput Middle Emulation Enabled Default (296):        0
        libinput Accel Speed (297):     0.000000
        libinput Accel Speed Default (298):     0.000000
        libinput Accel Profiles Available (299):        1, 1
        libinput Accel Profile Enabled (300):   1, 0
        libinput Accel Profile Enabled Default (301):   1, 0
        libinput Left Handed Enabled (302):     0
        libinput Left Handed Enabled Default (303):     0
        libinput Send Events Modes Available (273):     1, 0
        libinput Send Events Mode Enabled (274):        0, 0
        libinput Send Events Mode Enabled Default (275):        0, 0
        Device Node (276):      "/dev/input/event4"
        Device Product ID (277):        1390, 211
        libinput Drag Lock Buttons (304):       <no items>
        libinput Horizontal Scroll Enabled (305):       1

やはり正しく認識されているけれど、ボタンの数は9だと思われている。

1 2 3 4 5 6 7 8 9 

しかしxmodmapでは10ボタンだと思われている。

There are 10 pointer buttons defined.

    Physical        Button
     Button          Code
        1              1
        2              2
        3              3
        4              4
        5              5
        6              6
        7              7
        8              8
        9              9
       10             10

何度も言うが、 Ultimate Laser Mouse は12ボタンである

自力解決できず、フォーラムに質問してみたのだが、回答はつかなかった。 (解決した場合はこの記事を撤回し、投稿し直す予定)

H.264 vs H.265 vs VP8 vs VP9 vs AV1

実は先のビデオ関連の記事はMimir Yokohamaのほうにupしようかと思っていた。

こっちにしてよかった…Mimir Yokohamaのフォーマットで書いてたら絶対地獄を見た…

さて、先の記事の途中でAV1を試したが、実際AV1がどの程度使い物になるのか(いや、実際は強烈に遅いので全く使い物にならないのだが)試してみたくてちょっと検証してみた。

ソースビデオはコントラスト差、動きともに激しく、部分的にはほとんど更新されないドラムマニアのプレイ動画を使用した。 10MbpsほどのH.264ビデオである。

  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.12.100
  Duration: 00:00:04.79, start: 0.308970, bitrate: 9998 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, smpte170m/unknown/smpte170m), 1080x1920 [SAR 1:1 DAR 9:16], 9995 kb/s, 29.88 fps, 29.88 tbr, 15296 tbn, 59.75 tbc (default)
    Metadata:
      handler_name    : VideoHandler

libvpxはビットレートコントロールがうまくいかなかったことから、aomav1はそもそも変換できなかったことからこれらはrawvideoに変換し、それぞれvpxenc, aomencを使用して2パスで変換した。

メインビットレートはH.264で荒れる512kを選択。 VP8はあまりに小さいビットレートコントロールが困難だったため、512kについては200kを指定したCBRとした。

比較

ソース動画

Base H.264 @10Mbps

ソースは10Mbpsということもあり、暗い中非常にキレイに撮れている。 なお、撮影機材はZenfone Selfie(ZD511KL)である。

H.264

$ ffmepg -i base.mp4 -c:v libx264 -b:v 512k h264.mp4
H.264 @502kbps
H.264 @733kbps
H.264 @971kbps

そもそもH.264で荒れさせるのが基準だったため、512kでは動きのある部分は完全にブロックだし、パッド部分も相当粗い。

ビットレートが上がると順当にスムーズになっていき、素直な特性のようだ。

H.265

$ ffmepg -i base.mp4 -c:v libx265 -b:v 512k h265.mp4
H.265 @474kbps
H.265 @716kbs
H.265 @962kbps

現状最も有力なH.265。 さすがというか、静止画にすると打点のスティックが消えてしまっていて、VP9のほうが良さそうなのだが、 全体でみれば安定していてキレイ。動画では画質がよく感じられる。

全体的なざらつきがないので綺麗に見えるがこの静止画からわかるとおり動きの激しい部分でディティールがVP9よりも消えやすい。 ディティールにこだわる場合はビットレートに余裕を取るべきだと思うけれども、静止画に切り出す場合などはVP9のほうがうまくいく。

ビットレートが上がったときにも順当によくなっている。 H.264よりひとまわりいいといった感じで、ビットレートが上がると差は縮まり、ビットレートが非常に低いときはがんばっている感じだ。

H.265 (NVENC)

$ ffmpeg -i base.mp4 -c:v hevc_nvenc -b:v 512k h265-nvenc.mp4
H.265 (NVENC) @552kbps

NVENCは画質がよくないと言われているので、比較してみた。

テクスチャが雑で、なんか「下塗りです」といった感じ。 成る程、VP9 QSVのようにあからさまに目立つわけではないのだが、ディティールを見てしまうとなかなか厳しい。 利用できる状況は限られそうだ。

VP8

$ vpxenc --end-usage=cbr --bias-pct=0 --codec=vp8 --target-bitrate=200 --passes=2 -h 1920 -w 1080 -o vp8-cbr.webm raw.y4m
VP8 @586kbps

普及しなかったし残念なことになったVP8。768kならがんばってくれるが、512kはどうがんばっても到達せず、このセッティングでもちょっと大きめの586k。

画質は全体的にザラザラ。大きなブロックがないので静止画だとキレイっぽいけれど、常時こんな感じ(H.264なんかは部分的に、そしてちょいちょいブロック化してしまう感じである)なのでちょっとお話にならない。

何より目立つのは「色がおかしい」ことだが。

VP9

$ vpxenc --codec=vp9 --target-bitrate=512 --passes=2 -h 1920 -w 1080 -o vp9.webm raw.y4m 
VP9 @522kbps
VP9 @771kbps
VP9 @1020kbps

VP9は結構優秀で、H.264よりは良いし、H.265とどちらが良いかというと好みの問題と言えるくらいには仕上がっている。 ディティールを見ると損なわれ感があるのでやや厳しいが、ビットレートにある程度余裕を持たせればH.264よりも良い。

フリーコーデックに魅力を見ると感じるなら画質面ではアリだ。

だが、いかんせん遅い。x265の1/10くらいの速度である。 速度優先にしないと10fpsも夢のまた夢。

VP9もまともにマルチスレッドしないので、マルチスレッド化するだけでだいぶ実用になる気がするのだけど… (少なくともlibx265に負けない程度には)

ビットレートが上がるとH.265より良いように見える。 1Mbpsは完全に及第点だろう。

VP9 (QSV)

ffmpeg -init_hw_device vaapi=foo:/dev/dri/renderD128 -hwaccel vaapi -hwaccel_output_format vaapi -hwaccel_device foo -i invideo.mp4 -filter_hw_device foo -vf 'format=nv12|vaapi,hwupload' -c:v h264_vaapi -b:v 512k -c:a copy outvideo.mp4
VP9 (QSV) @555kbps

VP9を唯一実用する方法であるQSV。しかし、QSVのVP9は相当画質が悪い。 ビデオでの印象としてはVP8に近い。ちょっとこの品質ではよほど高ビットレートでない限り実用にならないという感じだ。 エンコードは100fpsほど出るのだが…

AV1

AV1はデフォルト設定では到底終わらないほどの時間がかかったため、次のようにした。

% aomenc --codec=av1 -t 40 --cpu-used=8 --target-bitrate=512 --passes=2 -h 1920 -w 1080 -o av1.mkv raw.y4m
Pass 1/2 frame  142/143    27456B    1546b/f   46186b/s   19657 ms (7.22 fps)
Pass 2/2 frame  142/142   298568B   16820b/f  502497b/s 2741931 ms (0.05 fps)

なお、どちらもスレッド数を指定しているが、AV1は完全にシングルスレッドで動作していた。

AV1 508kbps
AV1 @774kbps
AV1 @1032kbps

H.265よりもディティールが消え、のっぺりしている。 VP9とはほとんど見分けがつかないが、よく見ればなんとVP9のほうが良い。 VP9(512k)に対してAV1(512k)は

  • シャツの前のほうのシワが消滅
  • 打点部分のスティックが巨大なブロックによって消滅
  • シャツはのっぺりしてしまっている

と残念な結果に。

ビットレートがあがってもあまり改善していない。 速度優先の--cpu-usedのせいかもしれないがVP9の10倍は時間をかけた意味はどこへ…

追記: VP9/AV1 のマルチスレッド処理

テスト

コメントにてyusukeさんから

AV1がシングルスレッドでしか動かないのは–tile-columnsと–tile-rowsを指定していないからではないでしょうか

と情報頂いたので試してみた。

% aomenc --codec=av1 --cpu-used=8 --target-bitrate=512 --threads=16 --tile-columns=2 --tile-rows=2 --passes=2 -h 1920 -w 1080 -o av1-512-pararell.mkv raw.y4m

この場合、シングルスレッドで動作した。

% aomenc --codec=av1 --cpu-used=8 --target-bitrate=512 --threads=16 --tile-columns=6 --frame-parallel=1 --passes=2 -h 1920 -w 1080 -o av1-512-pararell.mkv raw.y4m

--tile-rowsをやめて、デコード用オプションである--frame-parallelを有効にしたところ、 マルチスレッドで動作した。 ただし、大部分はシングルスレッドで、ときどき6から10スレッド程度で動作するような挙動。

結果は

Pass 1/2 frame  142/143    27456B    1546b/f   46186b/s   19934 ms (7.12 fps)
Pass 2/2 frame  142/142   303279B   17086b/f  510444b/s 1562704 ms (0.09 fps)
aomenc --codec=av1 --cpu-used=8 --target-bitrate=512 --threads=16   --passes=  3502.70s user 67.02s system 224% cpu 26:29.29 total
マルチスレッドAV1 CPU利用率 (cpu-used=8)

CPUは200%越えてるけれど、速度的には2倍にはなっていない程度。

そして次の場合

% aomenc -w 1080 -h 1920 --tile-columns=6 --limit=48 -t 24 -b 8 --input-bit-depth=8 --end-usage=vbr --target-bitrate=512 -p 1 --webm --num-tile-groups=32 -o av1-512-parallel2.webm raw.y4m
Pass 1/1 frame  142/142   290129B   16345b/f  488306b/s 7850851 ms (0.02 fps)
aomenc -w 1080 -h 1920 --tile-columns=6 -t 24 -b 8 --input-bit-depth=8   -p 1  38460.66s user 114.83s system 491% cpu 2:10:55.73 total
マルチスレッドAV1 CPU利用率 (cpu-used=1)

ずっと激しく使われているのでなかなか効率はよさそう。 この違いは--cpu-usedにあるようだった。

--cpu-used=4の場合:

Pass 1/1 frame  142/142   295824B   16666b/f  497896b/s 1581372 ms (0.09 fps)
aomenc -w 1080 -h 1920 --cpu-used=$i --tile-columns=6 -t 24 -b 8    -p 1   -o  4379.28s user 54.32s system 279% cpu 26:26.07 total
マルチスレッドAV1 CPU利用率 (cpu-used=4)

--cpu-used=8より少し多めに動いている。

--cpu-used=2:

Pass 1/1 frame  142/142   297030B   16734b/f  499928b/s 3251395 ms (0.04 fps)
aomenc -w 1080 -h 1920 --cpu-used=$i --tile-columns=6 -t 24 -b 8    -p 1   -o  10423.02s user 70.17s system 322% cpu 54:16.15 total
マルチスレッドAV1 CPU利用率 (cpu-used=2)

結構動くようになった。

では待望の画質はというと

AV1 並列 cpu-used=1
AV1 並列 cpu-used=2
AV1 並列 cpu-used=4
AV1 並列 cpu-used=8

結構差は大きい。 cpu-used=8のAV1よりはcpu-used=1のVP9のほうが綺麗だけども、4だとディティールは潰れているけれどざらつきが減るため好みで済ませられるように思える。cpu-used=4より上であればH.265に対するアドバンテージは認められる。 のっぺりしているのはAV1のキャラクターのようだが、ノイズが消えるため感覚的には綺麗に見える。再変換したときに情報の欠落が気になりそうだが。

おまけ。同じセッティングでVP9を作ってみる(vpxencaomencはだいたいコマンド互換性がある)。 --num-tile-groupsは使えないので外し、--codec=vp9を追加する。

% vpxenc --codec=vp9 -w 1080 -h 1920 --cpu-used=8 --tile-columns=6 -t 24 -b 8 --input-bit-depth=8 --end-usage=vbr --target-bitrate=512 -p 1 --webm -o vp9-parallel.webm raw.y4m
Pass 1/1 frame  142/118   242873B 5835948 us 24.33 fps [ETA  0:00:01]    1125F   1298F  11937F    943F    792F    849F   1104F   1271F   1022F   1030F  24348F   1382F   1316F   1264F   2220F   1162F   1152F   1072F   1084F   1386F  13097FPass 1/1 frame  142/142   316309B   17820b/f  532379b/s 6950835 us (20.43 fps)
vpxenc --codec=vp9 -w 1080 -h 1920 --cpu-used=8 --tile-columns=6 -t 24 -b 8    16.91s user 0.73s system 235% cpu 7.478 total

おぉぉ、速いぞ!!! 実用になるぞ!!!よくみたらちょこっとだけ粗いけれど、全然いけるいける。

VP9 並列 cpu-used=8

ただ、--cpu-usedしないとさすがに厳しい。

% vpxenc --codec=vp9 -w 1080 -h 1920 --tile-columns=6 -t 24 -b 8 --input-bit-depth=8 --end-usage=vbr --target-bitrate=512 -p 1 --webm -o vp9-parallel-used1.webm raw.y4m     :(
Pass 1/1 frame  142/118   242579B   50719 ms 2.80 fps [ETA  0:00:10]    1121F   1252F  11933F    982F    752F    916F   1059F   1293F    973F   1027F  21951F   1641F   1210F   1324F   2162F   1095F   1044F   1052F   1099F   1382F  13774F Pass 1/1 frame  142/142   314260B   17704b/f  528930b/s   60777 ms (2.34 fps)
vpxenc --codec=vp9 -w 1080 -h 1920 --tile-columns=6 -t 24 -b 8    -p 1 --webm  143.78s user 1.13s system 236% cpu 1:01.31 total

所感

これをテストした上での感想としては

  • --cpu-used=1 はとても遅い。VP9でもかなり厳しい
  • --cpu-used=8 はあまり効果がなく、 --cpu-used=4 が軽量設定としてはよさそう
  • 確かに画質は良いが--cpu-used=8だと悪い。--cpu-used=1でx265並の速度が出れば革命的だけども…
  • マルチスレッドはVP9よりはAV1で改善されている
  • しかしAV1であっても対してCPUを活用できておらず、いまいちと言われているx265のほうがよっぽど計算リソースを有効活用する
  • だいたい活用できているのは8スレッドあたり。クロスしている部分を考慮しても12スレッド
  • AV1はいくらスレッド数を多く指定しても現実的な速度にならない。4114が遅いとしてもCOre i7であってもコアあたり8倍は速くないので、10FPSには到達しない感じ
  • スレッド数を増やしてもせいぜい2倍程度しか速くならないため、スレッド数よりも--cpu-usedのほうが影響が大きい
  • VP9の--cpu-used=4は速度的にも(うちでは30FPS出ないが)使えるが、H.265(libx265)との差は開いてしまい、よほど強い動機がないと厳しい (--cpu-used=2でも結構粗い)
  • AV1がハードウェア支援されたら使えるかというと、現状QSVのVP9がひどいという言葉では片付けられないくらいひどいので、全く期待できない

基本的には「向上するソース画質に対して可能な限り損なわないようにする」には「ソースサイズが大きくなったとき(あるいは画質が向上したときに)に同等ビットレートでソースの改善を反映できるように」動画コーデックは進化しているのであり、つまり情報の少ないソースであれば結果的により小さなサイズに圧縮できる、ということを反映意味する。

そのことを踏まえれば、「画質とサイズを妥協すれば新しいコーデックでも実用できる」というのは完全に本末転倒であり、全く価値がない。これは速度的にVP9の最高画質とAV1の最低画質が同ビットレートで逆転し、かつVP9のほうが速い、というのはまさにそれだ。

確かにAV1の画質は魅力的だが、それはあまりにも現実的ではないリソースをつぎ込めばという話である。 それをいくらか緩和しようとした時点でAV1の画質というメリットは損なわれてしまい、VP9のほうがまだマシという結果になる。

もちろん、一般で使われることは最初から投げ捨てて、配信者向けに作っているのでありユーザーには関係ない、というのであればわからなくはないが、現状のAV1はそれこそGoogleクラスでなければ実用できないようなものであり、ユーザーはデコードすらままならない。 そうすると単に「特殊で扱いにくいもの」になってしまい、そのようなものがどんな経過をたどり今残っていないのかということを完全に忘れ去ってしまっているように思う。

現状は、一般ユーザーにとってVP9であれAV1であれ利用を考慮する価値のないものであり、 フリーであることの価値を理解するのであればVP9は考えられるがAV1は存在自体忘れていても構わない。

ユーザーが使うならばH.265(あるいはH.264)が良い。 (特許問題など気持ち悪いとは思うが…)

画質、処理速度、コスト、処理の安定性などH.265(x265)の何が好まれていて、何を達成しなければならないのか、優位性を口にするくらいなら真剣に考えて欲しいと思う。

【まとめ特集記事】 ビデオカード * VDPAU / VA-API * ffmpeg

パッケージ名などはArch Linux/Manjaro Linux準拠である。

PRIME(異なるメーカーのビデオカード混合)の話はしていない。 (持っていないので) そのうちするかもしれない。

ffmpeg周りに関しては過去の記事には載せてなかった話も色々書いた大作になっている。 (特にAMD関連の情報やVDPAUなんかはドキュメントが少ないので有益なはず)

ビデオカードとドライバ

現在使用されているビデオカードは次の3メーカー。

  • Intel
  • Nvidia
  • AMD

Intelはコンシュマー向けIntel CPUに内蔵されているビデオカードである。 Intel CPUでもごく一部AMDビデオカードを内蔵したものもある。

NvidiaはGeForce/Quadro/Teslaビデオカード、AMDはRadeonビデオカード(AMD APU内蔵のものを含む)のことである。

ビデオカード ドライバー タイプ 現状
Intel intel free Supported
Nvidia nvidia non-free Supported
Nvidia nvidia-tesla non-free Supported
Nvidia nouveau free Supported
Nvidia nv free Deprected in 2010
AMD AMDGPU free Supported
AMD Catalyst non-free Legacy
AMD ATI/Radeon free Legacy
AMD radeonhd free Obsolated?
  • IntelとAMDのオープンソースドライバはメーカー協力のもと作られており、現状唯一の選択肢
  • AMDGPUは新しいドライバで新しいカードしかサポートしておらず、それ以前のものはATI及びRadeonドライバのサポート
  • プロプライエタリのCatalystドライバも更新されておらず、古いカード向け
  • nouveauドライバはメーカーサポートがないリバースエンジニアリングの賜物

ハードウェアビデオアクセラレーション

ハードウェア搭載機能

Intel

IntelはQSV(Quick Sync Video)という補助機能を搭載。 割とビデオが重かった時代から、ビデオを快適に再生できるようにビデオカードの力を借りて再生するものである。

そのため、QSVはビデオカードだけでなくCPUパワーも併用する。

NvidiaやAMDよりも非力だが、サポートしている形式が多く、意外と使いやすい。 また、画質がちょこっとだけいい。

Nvidia

Nvidiaはエンコード用のNVENCとデコード用のNVDECという2つの専用チップを搭載。 CUDAコアは利用していない。

IntelやNvidiaと比べ桁違いに高速。 GTX1080でFHD動画をH.264で1300FPS、H.265でも650FPSで処理できるという。

AMD

AMDはエンコード用のVCE(Video Coding Engine)、デコード用のUVD(Universal VideoDecorder)を搭載。 AMDも全然宣伝していなくて、情報がとにかく少ない。

VCEの速度的にはライバルNvidiaカードのNVENCの半分くらいが相場…らしい。 また、サポートしているフォーマットが結構少ない。あとからアップデートでサポートされたりもしているが。

Linux用のAPI

VDPAUはNvidia主導の、VA-APIはIntel主導のAPI。

VDPAUは再生のみ。VA-APIはエンコードもできる。

API エンコード デコード
VDPAU x o
VA-API o o

当然NvidiaはVDPAU、IntelはVA-APIをサポート。AMDはオープンソースドライバーでは両方サポート、CatalystはVA-APIのみ。

カード VDPAU VA-API
Intel x o
Nvidia o x
AMD non-free x o
AMD free o o

それぞれアダプタを使用してVDPAUをラップしてVA-APIで処理する方法や、VA-APIをラップしてVDPAUで処理する方法がある。 (libvdpau-va-gl及びlibva-vdpau-driver) これによってIntelでVDPAUを、NvidiaでVA-APIを処理できる。

VDPAUアダプタを使う場合、環境変数としてVDPAU_DRIVER=va_glする必要がある。

AMDの場合VA-APIとVDPAU両方をアダプタにすることが可能だが、それをするとエラーになる。 また、このVDPAUに対応させ、VA-APIをアダプタにするとエンコードはできなくなる。

nouveauドライバの注意点

nouveauドライバでVDPAUを使うにはプロプライエタリドライバのフォームウェアを流用したバージョンが必要で、 NVENCは利用することができない。

プレイヤーでデコード

VLC

ツール → 設定 → ビデオ → ディスプレイ → アウトプット → VDPAU出力 (もしくは自動)

ツール → 設定 → 入力 / コーデック → Hardware-accelerated decoding → VDPAUビデオエンコーダー or VA-APIビデオエンコーダー

SMPlayer

オプション → 環境設定 → 全般 → ビデオ → 出力ドライバー → vdpau or vaapi

GStreamer

gstreamer-vaapi (VA-API) 及び gst-plugins-bad (VDPAU) パッケージを導入

mpv

または

mpvの場合NVDECを直接叩くこともできる。

さらにCUDAも使える。

MPlayer

VDPAUの場合

VA-APIはフォークでサポート。mpvのほうがおすすめ

Xine

詳しくは

Dragon Player

できないっぽい。

Kaffeine

多分できない。

もしVLCがコマンドラインでVDPAUあるいはVA-APIの使用を受け入れるならなんとかなる。

FFMpeg

基本編

マルチメディアフレームワークffmpeg。だいたい動画を操作するときはスイスナイフのように使える。

まずは基本

ffmpegは出力の拡張子を見る。なのでちゃんと指定することが必要。

オプション指定は順序が決まっている。

ffmpeg [global_options] {[input_file_options] -i input_url} ... {[output_file_options] output_url} ...

おおまかなグループで間違えなければ大丈夫そうだけれども、順番が問題になることは覚えておくといいかもしれない。

それでは古いreal mediaを今風にH.264+aacのmp4にしてみる。

-c:v = -vcodec (video codec)で、 -c:a = -acodec (audio codec)。

これでは品質指定ができないので、ビットレートを指定してみる。

H.264で色々する

H.264はだいたい標準的なビデオフォーマット。 標準のソフトウェアビデオコーデックはlibx264。

libx264はビットレートではなく品質で固定する-crfオプションが利用できる。

-crfしていてもオーディオは固定することもできる。

速度が問題になるケースでは-presetが有効。 選択肢はx264 --helpで確認可能。

あまり使われないけれども有用なオプションとして-tuneがある。 主には実写用のfilmとアニメーション用のanimationを使うことになるだろう。 フィルムグレインを損なわないためにgrainを使うことも考えられる。

また配信用にはzerolatencyも有効だ。

2-passエンコーディングで画質が〜と言っている人がいるが、基本的に2-passエンコーディングはファイルサイズをより正確にするためのものである。 詳しくはこの日本語訳あたりを。

x265もだいたい同じような感じで使える。

さらに色々する

動画から先頭4秒を切り出す

開始30秒のところから5秒切り出す

以前は-ss-iより後のほうがよかったらしい。 また、エンコードしないと不具合が出るので-c:v copyはできない。

動画の開始10秒から10秒分を1秒あたり2枚で静止画に切り出す

動画をリサイズする

動画をクロップする

左上から200×200の座標を起点に、1600×900の動画で切り出す。

連番動画からGIF動画を生成

フレームレートは5FPSで作ってみる。

音声を遅らせる(早める)

音ズレを解消する。

次の例では音声を1.5秒遅らせる。

逆にビデオを1.5秒遅らせる

これは理解が難しいので解説。

-itsoffset 1.5 でその入力ストリームを1.5秒遅らせている。 2つ指定している入力ストリームが両方同じファイルなので、同じファイルがソースになっているのだけど、

  • 入力0は1.5秒遅れたinvideo.mp4
  • 入力1はそのままのinvideo.mp4

になる。

この入力0, 1, 2, 3…はあくまで入力ソースなので、これ自体は特にその動画のなにを使うということに影響はない。

ffmpegは複数の指定した入力ストリームをマージする。 単純に複数の-iを並べた場合、どうなるかはいまいち制御できないようだ。確かなのは、オーディオチャンネルのないビデオと、オーディオを入力ストリームとした場合、確実にそのビデオとオーディオが合成される。

基本的にはffmpegは#:0にビデオ、#:1にオーディオというファイルを作るようだ。 これは3つ以上のファイルをマージした場合でもである。

そして複数のビデオトラック、あるいはオーディオトラックを持たせるには-mapを使う。 例えば音声のないビデオinvideo.mp4とオーディオinaudio1.aac, inaudio2.aacがあったとして

では単純にinvideo.mp4のビデオとinaudio1.aacのオーディオが合成され、inaudio2.aacは無視される。 invideo.mp4が音声を持っていた場合はinaudio1.aacも無視される。

ここで-mapを使い

  • 入力0のストリーム0
  • 入力1のストリーム0
  • 入力2のストリーム0

を合成させる

ここで-map 0:0 -map 0:1 -map 1:0として、オリジナルのビデオに追加のオーディオトラックを合成する、というようなことも可能だ。

ソースは複数のストリームを持てるので、何番のストリームに何が入っているかはffprobe fileとすることで知ることができる。

さて、元の話に戻ろう。#:0がビデオ、#:1がオーディオの一般的なビデオファイルであるならば、同じビデオファイルをソースとする「1.5秒遅れた入力0」と「そのままの入力1」を合成したとき、入力0のストリーム0と入力1のストリーム1を合成すればビデオが遅れるし、入力0のストリーム1と入力1のストリーム0を合成すれば音声が遅れるわけである。

コントラストを上げる

mpvで2を押すほうが簡単なのであまり使わないけど、暗いところで撮影した動画をupする場合などには少しコントラストを上げたほうが見やすい動画になる。

さらにブライトネスもちょっと上げたいなと思ったらこんな感じ。

お手軽にビデオ/オーディオをなしにする

ノイズを避ける場合や抽出したい場合に使える。

ビデオなしのオプションは-vn、オーディオなしのオプションは-an。 サブタイトルなしの-snもある。

VDPAU/VA-API/NVENC

再生支援

VDPAUの場合。これはあまり資料がない。単純には

並列で複数のストリームを扱う場合は名前をつけよう。ここではvdpauストリームにfooという名前をつけて扱っている。

VA-APIの場合も同じ感じ。ただ、VA-APIデバイスの指定が必要。

複数扱えるようにするには名前をつける。

エンコード支援

VA-APIでは同じようにデバイスを指定し、ビデオフィルタでVA-APIにアップロードし、VA-APIハードウェアコーデックでエンコードする。

コーデックは「エンコードに何を使うか」なので、libx264を指定すればソフトウェアコーデックであるx264が使われる。 ここではVA-APIのハードウェアコーデックを使用する。

なお、A10-7870K (Radeon R7)をAMDGPUで使ったときは、-profile 578してあげないとうまくいかなかった。

VA-APIで利用できるコーデックはこんな感じ。もちろん、ハードウェアとドライバが対応していればの話。

フォーマット VA-APIコーデック
H.262 / MPEG-2 part 2 mpeg2_vaapi
H.264 / MPEG-4 part 10 (AVC) h264_vaapi
H.265 / MPEG-H part 2 (HEVC) hevc_vaapi
MJPEG / JPEG mjpeg_vaapi
VP8 vp8_vaapi
VP9 vp9_vaapi

VDPAUはデコード専用でエンコードには使えない。 Nvidiaビデオカードの場合、ffmpegからNVENCが利用できる。ただし、nouveauドライバでは不可。

H.265(HEVC)の場合はhevc_nvenc。オプションがちょっと違ったりする。

再生もエンコードも支援

VA-APIの場合は結構使うようだ。

基本的には組み合わせなのだけれど、出力フォーマットにvaapiを指定する必要があり、項目は2つ増えている。これはちょっと複雑。

NvidiaのVDPAU+NVENCはほとんど見かけないけれども、NVENCの使い方が単純にNVENCハードウェアコーデックを指定するだけなので、単純な組み合わせになる。

他のコーデックを使う

コピー

copyはビデオ、オーディオともに利用でき、エンコードを行わず単純にストリームをコピーする。

エンコードを行わないので劣化が発生しない。 「ビデオだけ加工したい」といった場合に多用する。

ビデオ

H.265(HEVC)

H.264よりもファイルサイズあたりの品質がいい。 特許問題でものすごくドロドロしているけれども、今のところ主流である。

ソフトウェアコーデックとしてはx265があり、libx265として利用可能。 オプションはほぼlibx264と同じ。

主流だけあって最新のハードウェアなら3メーカーともサポートしており、hevc_vaapihevc_nvencが用意されている。

コンテナは主にはAACと組み合わせて.mp4。それ以外を使うなら.mkv

VP8

Googleが推進していた、全然流行らなかったコーデック。

コンテナはOgg Vorbisと組み合わせてWebM。 品質はあまりよくない。

VP9

Googleが推進するコーデック。 H.265がドロドロしすぎているので、配信なんかでは結構使われている。YouTubeでも使われている。

指定方法がVP8と全然違う。 この方法だと変な品質のができるので

こっちのほうが安全。

画質はなぜか相当粗い。そしてサイズが非常に大きい。 あと、めちゃくちゃ遅い。なかなか思うようにコントロールできない。

コアあたりの速い16コアまでのCPU(具体的にはCore i7あたり)で、-thread 16 -speed 8とかやれば、耐えられないこともないかもしれない。

H.264のライバルらしいけれど、これをライバルと呼ぶのはちょっと無理がありすぎる。 特に低ビットレートになると差は歴然である。 高ビットレートなら意外といけるらしいが、今度は時間が耐え難い。

Intel QSVがVP9エンコーダを搭載しているのだけど、そっちを使うとさらにひどいことになる。

AV1

待望のH.265のライバルであるフリーなコーデック。

ffmpeg 4.0からついに投入されたのだけれど、私の手元では耐えるのは不可能な速度だったので、現実味はまったくなかった。 どうもlibx265と比べても時間は10倍ではきかない感じだ。 デコードも超重いらしい。

生ビデオにしてからaomencでやることはできた。 …といってもだ。

Pass 1/2 frame 3219/3220  618240B    1536b/f   23040b/s  207846 ms (15.49 fps)
Pass 2/2 frame   20/1      41244B  212969 ms 5.63 fpm [ETA 190:22:59] 1.771 40.510 45.055 49.142   41244F

このくっそ軽い動画で、5.63fpm(fpsではない。fpmである)。 190時間エンコードにかけるという。仮にも20コアXeonでだ。(aomencのマルチスレッドはゴミのようなものだが)

ふざけているのだろうか… libx265の10倍遅い、と言われているが、10倍どころではないだろう。だって、このマシンはlibx265でもだいたい30fpsくらい出るのだから。5fpmといったら、1/360のスピードである。

最終的には18fpm程度になり、3000フレームほどの動画を約4時間で済ませた(平均0.28fps)。

画質は明らかに粗い。とはいえVP9よりはマシ。 今更これを出されても、しかもこんなに重いのでは話にならない…という気がする。 100倍速ければ使う、という感じ。(平均すれば30fps出る程度)

オーディオ

mp3

品質は高くないけれど便利なMP3。

192kbpsのmp3を作る場合

-q:aするとVBRになる。小さいほうが高品位。

Ogg Vorbis

高品位かつフリーなコーデックとして人気のOgg Vorbis。 サポートされていることも多いので有力。vorbisよりlibvorbisのほうが高品位。

-qファクターは大きいほうが高品位。これはogenc-qにそのまま渡されるらしい。

ポータブルオーディオにはこれが良い。

Ogg FLAC

こちらもサポートされていることが多いロスレスのオーディオフォーマット。 ロスレスなので音質は損失しない。

CPUをたくさん使ってより圧縮することができる。 この圧縮レベルは音質には影響しないが、サイズの差は小さい。

容量に余裕があるなら使っていきたい。

Opus

SILK+CELTがベースになっていて低ビットレートではSILKのようにスピーチ用に可聴音域に特化し、高ビットレートではSILKベースのレイヤーを省いて高品位に再生するオーディオコーデック。

Opusは低ビットレートのHE-AAC、中ビットレートのAAC、高ビットレートのVorbis, AACと比べてより良い品質を提供する。 しかもフリーである。

素晴らしいのだけれど、動画では使いようがあるのに対して音声だと再生できるプレイヤーが割と少なくて困る。 WebMが標準でOpusをサポートしているのにAndroidがOpusをサポートしてないあたりもまた困る。

このため、Opusの出番は

  • ヴォイスレコーディング。 だいたい64kか92k。
  • もともと品質の高くないlossy audioの再変換。同ビットレートなら損失は微々たるもの
  • WebM。VP9との組み合わせが一般的。
  • H.264やH.265と組み合わせ、コンテナをMKVにする

H.265 + Opus の MKV は私の最近のお気に入り。 (ウェブカムのところを見て欲しい)

録音 with Pulse/ALSA

ffmpegがALSAに対応しているので簡単。

レコーディングするデバイスや調整はpavucontrolなどのPulseAudioミキサーでやると便利。

ウェブカム録画

Video4Linux2を使ってウェブカムからの録画が可能。 次の例ではウェブカメラデバイス/dev/video0から録画している。

音声も録音したいなら組み合わせ

カメラの場合はカメラが撮れるフォーマットでしか撮れない。 まずは確認する。以下は定番のLogicool C270。

$ v4l2-ctl --list-formats
ioctl: VIDIOC_ENUM_FMT
        Index       : 0
        Type        : Video Capture
        Pixel Format: 'YUYV'
        Name        : YUYV 4:2:2

        Index       : 1
        Type        : Video Capture
        Pixel Format: 'MJPG' (compressed)
        Name        : Motion-JPEG
% v4l2-ctl --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
        Index       : 0
        Type        : Video Capture
        Pixel Format: 'YUYV'
        Name        : YUYV 4:2:2
                Size: Discrete 640x480
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 160x120
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 176x144
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 320x176
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 320x240
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 352x288
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 432x240
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 544x288
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 640x360
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 752x416
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 800x448
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 800x600
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 864x480
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 960x544
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 960x720
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1024x576
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1184x656
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1280x720
                        Interval: Discrete 0.133s (7.500 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1280x960
                        Interval: Discrete 0.133s (7.500 fps)
                        Interval: Discrete 0.200s (5.000 fps)

        Index       : 1
        Type        : Video Capture
        Pixel Format: 'MJPG' (compressed)
        Name        : Motion-JPEG
                Size: Discrete 640x480
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 160x120
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 176x144
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 320x176
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 320x240
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 352x288
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 432x240
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 544x288
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 640x360
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 752x416
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 800x448
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 800x600
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 864x480
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 960x544
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 960x720
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1024x576
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1184x656
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1280x720
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1280x960
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)

センサー自体が4:3なので、一応仕様上は1280×720のカメラだと謳っているけれども、最大は1280×960。

画質をとってrawvideoの752×416

あるいは画質は劣悪だけれどもピクセル数重視でMotionJPEG。 もともとデータがMotionJPEGで送られてくるので再エンコードはいらない。

音声も録音するならOpusでMKVかな

スクリーンキャスティング (X server)

XのAPIを使って画面の録画ができる。

300×300のウィンドウを左上から200×200のオフセットで録画する場合

さらに録画領域を表示する場合

クリックしたウィンドウを録画する(zshスクリプト)。 さらにマイク録音も加えた。

コンピュータの音とマイクの音両方を録音したい場合。 環境に依存する箇所が多いので注意。

まずは確認。

$ pacmd list-sources

あとはこんな感じ

$ pacmd load-module module-null-sink sink_name=mixmic
$ pacmd load-module module-loopback source=alsa_output.pci-0000_00_1f.3.analog-stereo.monitor sink=mixmic
$ pacmd load-module module-loopback source=alsa_input.usb-046d_0825_D457DB60-02.analog-mono sink=mixmic

スクリーンキャスティングしている内容を仮想カメラにする (v4l2 loopback)

スクリーンキャスティング機能のないメッセンジャーで通話しているときにカメラとして使えることでスクリーンを写せるというメリットがある。

要v4l2loopback カーネルモジュール。

$ sudo modprobe v4l2 video_nr=1
$ ffmpeg -re -f x11grab -video_size hd1080 -i $DISPLAY -f v4l2 -r 60 -vcodec rawvideo -pix_fmt yuv420p /dev/video1

video_nrで作成するデバイス番号を指定している。 video_nr=1なので/dev/video1。4から6を作成したいなら video_nr=4,5,6

hd1080ってなんぞ、ということについては公式ドキュメント参照のこと

サマータイムの恐怖

日本が、サマータイムを導入しようとしているらしい。

これだけでも狂気の沙汰であるが、それも2時間もの幅で、それも2年間限定だという。

前代未聞の愚行だが、なんとそれを支持する人が過半数であるという。

都市機能が麻痺し、日本が国際的信用が損なわれ、人命が失われるまさにサイバーテロなのだが、 「日本は自国にサイバーテロを発生させよ!!」と考えているのだろうか。

これがどけほど愚かしいかは詳細に解説するには私には知識が足りないし、 外でも色々と解説されているので、部分的に切り取ってお話しようと思う。

これはほんとひとかけらにすぎないことを理解してほしい。

もっと理解したければ、Togetterに秀逸なまとめがある

サマータイムの難しさ

まつもとゆきひろ氏いわく

Rubyの生みの親であるまつもとゆきひろ氏が著書「コードの世界」の中で次のような話をしている

個人的な経験になりますが,2007年11月に米国,ノースカロライナ州で開催されたRUbyConfの最終日と、2008年3月にチェコのプラハで開催されたEuRuKoの2日目が,ちょうどサマータイム切り替えの日でした。 どちらも前日から主催者が繰り返し「明日からタイムゾーンが切り替わるから時間を間違えないように」と叫んでいましたが,それでも時計を合わせるのを忘れる人がそれなりにいたようです。 ホテルの部屋の時計も自動で調整されるわけではないので,かなり注意しないとうっかりミスをする人が続出しそうです。 電波時計なら自動調整されますが,国中すべての時計をいっせいに電波時計にするわけにもいきませんしね。

ずいぶん昔のことになりますが,Ruby 1.4.4のころ (2000年ころ) には,このサマータイムの扱いにバグがありました。 そのころようやく増え始めたヨーロッパのユーザーからのレポートで発覚したのですが,サマータイムの始まりと終わりの数時間だけ時刻がズレるという典型的な境界条件バグでした。 日本にはサマータイムがないので,私自身が問題を理解できず,このバグを直すのに大変苦労しました。 この経験から,安易なサマータイム導入は,ソフトウエアのトラブルを多発させることになり,最悪の場合,社会問題に,そうでなくても,人知れず数多くのプログラマが涙を飲むことになりそうなので,とても賛成できません。

巻き戻る時間、消失する時間

サマータイムが難しいのはなんといっても「時間が直線状に進まなくなる」ことである。

たとえば、2020年8月1日 00:00:00(JST)に夏時間(DST)が適用になるとする。 すると、2020年7月31日 23:59:59の次の1秒は2020年8月1日 2:00:00になる。 つまり2020年9月1日の0時から2時が消滅する。

一方、2020年9月1日にDSTが終了すると、が2020年8月31日 23:59:59の次は2020年8月31日 22:00:00である。 つまり、2020年8月31日の22時から24時までの間は2回繰り返される。

この場合、たとえば

  • 2020年8月31日23時放送予定の番組はJSTなのかJDTなのかによって2時間ズレる
  • 約束の時間を設定してしまうとすれ違いが発生しうる
  • 日中にやるとさらに問題は深刻に。就業時間も2時間伸びる
  • 0時更新とすると「日をまたぐ瞬間」がなくなってしまう。日次、月次でスケジュールされているジョブが発生しない可能性があり、重大事故が発生する可能性もある

ちなみに、サマータイムの想像はまつもとゆきひろ氏が苦戦していることからも明らかだと思うが、想像よりずっと難しい。 実際私もこれを書いている最中に、「サマータイムに入るときに時間が戻り、サマータイム終了時に時間が進む」と思って途中まで書いていた。 正解は逆である。

UTCから単純計算できない問題

日本は国内時差がないため、基本的にJSTは単純にUTCからオフセットした時間として扱えていた。 ここにJDTが加わるとJSTは計算可能な基準の値ではなくなってしまう。

たとえば日本から5時間戻る時差の場所(UTC+4)へサマータイムをまたいで7時間で移動すると、出発したときから日本の時計を見ていなければ時計上は2時間後に到着したように見えるが、日本の時計から見れば同時刻に到着したように見える。

まず、これが理解できない、特に自分が殊更に理解できないのではなく当たり前に理解できないものだと思うのであれば、サマータイムには断固として反対すべきである。 日本に関わる全ての人がこれを理解して新しい時間を取り扱うよりほかにないのだから。

解説すると、2020-07-31 22:30:00 JSTにアルメニアに向けて7時間で到着する直行便(存在しないが)で出発したとすると、 到着するのは2020-08-01 00:30:00 に到着するが、日本の時刻は2020-08-01 07:30:00 JDTになっている。 2020-08-01 00:30:00はJSTでもJDTでも実際に訪れることはないのだが、2020-07-31 22:30:00 JST = 2020-08-01 00:30:00 JDTである。なので、出発時刻をJDTで見れば同時刻に到着している。

さらにサマータイムをまたいで帰ると今度は16時間後に到着…するわけではなく、12時間後に到着する。

2時間

実はDSTは1時間と書かれていたりして、「サマータイムが2時間」なんていうのは想定外である。 そのため、DSTをフラグ管理していて、DSTが真である場合標準時に1時間を足す、という処理は結構一般的だったりする。

これを2時間のサマータイムなんて導入すると、世界中が大迷惑である。

しかもだ。 JDTはすでにある。

日本でも4年間ほどサマータイムが導入されたことがあり、そのために日本の時刻情報としてこの4年間JDTが運用された記録が残っている。

% date --date="70 years ago"
Thu Aug 19 18:54:05 JDT 1948

なのでJDTは使うことができず、新しい名前をつける必要があるのだが、 命名規則から外れた名前を、しかもサマータイム用に作る必要が生じる。

2年間のために世界中に恒久的に維持・管理しなければいけない複雑なデータをひとつ増やすわけだ。 迷惑も甚だしい。

単純に作業するだけでも経済損失は日本円換算で何十億、何百億では済まないだろうとは思う。

TZのないデータフォーマット

YAMLの場合

% date; ruby -r yaml -e 'puts YAML.dump Time.now'
Sun Aug 19 16:27:15 JST 2018
--- 2018-08-19 16:27:15.749864798 +09:00
...

日のみだとRubyはTimeZoneのないDateクラスを使用する。

% ruby -r yaml -e 'pp YAML.load(ARGV[0])' "ts: 2018-08-19"
{"ts"=>#<Date: 2018-08-19 ((2458350j,0s,0n),+0s,2299161j)>}

日時のみの場合はUTCとみなす

% ruby -r yaml -e 'pp YAML.load(ARGV[0])' "ts: 2018-08-19 05:00:00"
{"ts"=>2018-08-19 14:00:00 +0900}

TZをつけるとちゃんと認識してくれる。

% ruby -r yaml -e 'pp YAML.load(ARGV[0])' "ts: 2018-08-19 05:00:00 +9" 
{"ts"=>2018-08-19 05:00:00 +0900}

JSTだとは認識していない(タイムゾーンでなく時差で認識している)けれど、通常は問題ないはず。 リアルタイムでカウントする場合は問題だけれども、Rubyのレイヤーではそれはその瞬間に異なる時差が適用されるはずだから。

人間が書いたデータに必須でもないのにタイムゾーンが書いてあるなんてほとんど見たこと無いけれど。

日時情報はあるけれどタイムゾーンがないデータを持っているもので最も使われているのはExcelである

Excelマクロで提示処理、あるいは時刻に基づく集計処理をしている皆さん。 ご愁傷さまです。

AMD APU (A10-7870K Godavari) * Radeon VCE * AMDGPU * VA-API * ffmpeg

理屈としては解説してきたものの、実際にVA-APIでVCEを叩いたことがなかったのでやってみた。 ついでなので、qsvやnvenc、あるいはlibx264などでも応用できるウェブカメラとスクリーンキャスティングの話もしておく。

基本的な手順は単純で、AMDGPU(事実上現在唯一となったAMDビデオドライバ)を選択した上で、 VA-APIを有効にし、VA-API経由でエンコーディングを行う。

注意点としては古くなったプロプライエタリドライバ(Catalyst)ではなく、AMDGPUドライバーを使用することと、 MESA VAドライバを使用することである。

RadeonはVA-API/VDPAUの両方をサポートしており、NvidiaのようにVDPAUドライバをインストールし、VA VDPAUアダプタを使用するという方法(libva-dvpau-driver)も成立してしまう。 しかし、この場合は動作しなくなるので、必ずMESA VAドライバ(libva-mesa-driver)を使用する必要がある。

その上で基本はこんな感じ。 (Arch/ManjaroのffmpegはVA-APIを含んでいるのでffmpeg云々の話はない)

$ ffmpeg -vaapi_device /dev/dri/renderD128 -i source.avi -vf 'format=nv12,hwupload' -c:v h264_vaapi -qp 24 -c:a copy outfile.mp4

ffmpeg上でのVA-APIは公式にドキュメントがある

ソースファイルがビデオアクセラレーションが効くのであればUVDをVA-API経由で叩いてデコードすることもできる。

$ ffmpeg -vaapi_device /dev/dri/renderD128 -hwaccel vaapi -hwaccel_output_format vaapi -i source.avi -vf 'format=nv12,hwupload' -c:v h264_vaapi -qp 24 -c:a copy outfile.mp4

ところがこれではうまくいかなかった。 一件成功しているように見えるのだが、フレームの全くないビデオファイルが出来上がってしまい再生できない。

多分、新しいRadeonだとそんなことはないのだろうと思うけれども、Godavari(2015年)のR7グラフィックスでは問題があったため、-profile 578を指定すると解決した。

$ ffmpeg -vaapi_device /dev/dri/renderD128 -i source.avi -vf 'format=nv12,hwupload' -c:v h264_vaapi -profile 578 -bf 0 -qp 24 -c:a copy outfile.mp4

ウェブカムからキャプチャする場合はエンコードのみ、入力はv4l2:

$ ffmpeg -vaapi_device /dev/dri/renderD128 -f v4l2 -i /dev/video0 -vf 'format=nv12,hwupload' -c:v h264_vaapi -profile 578 -qp 24 outfile.mp4

さらにマイクをPulseAudio経由で拾う場合。音声は192k AAC:

$ ffmpeg -vaapi_device /dev/dri/renderD128 -f v4l2 -i /dev/video0 -vf 'format=nv12,hwupload' -c:v h264_vaapi -profile 578 -qp 24 -f alsa -i pulse -c:a aac -b:a 192k outfile.mp4

X11のスクリーンキャスティング 音声つき。 A10-7870Kだとh264_vaapiは34fpsくらいなので、60fpsはフレーム落ちばかりになる。30fpsも無理で24fpsがドロップしない限界。 ultrafastにした場合は30fpsは可能だけれど60fpsは無理。

$ ffmpeg -vaapi_device /dev/dri/renderD128 -f x11grab -framerate 24 -video_size 1920x1080 -i $DISPLAY -vf 'format=nv12,hwupload' -c:v h264_vaapi -profile 578 -qp 24 -f alsa -i pulse -c:a aac -b:a 192k outfile.mp4

ultrafastで30fps:

$ ffmpeg -vaapi_device /dev/dri/renderD128 -f x11grab -framerate 30 -video_size 1920x1080 -i $DISPLAY -vf 'format=nv12,hwupload' -c:v h264_vaapi -profile 578 -preset ultrafast -qp 24 -f alsa -i pulse -c:a aac -b:a 192k outfile.mp4

なお、-video_size-iよりも先に指定することが必須である。基本的にffmpegはオプションは順番に厳しい。

300×300のウィンドウを左上から200×200のオフセットで録画する場合

$ ffmpeg -vaapi_device /dev/dri/renderD128 -f x11grab -framerate 30 -video_size 300x300 -i $DISPLAY+200,200 -vf 'format=nv12,hwupload' -c:v h264_vaapi -profile 578 -preset ultrafast -qp 24 -f alsa -i pulse -c:a aac -b:a 192k outfile.mp4

-video_sizeの指定方法は色々あって、公式ドキュメントで解説されている。 なので、-video_size 1920x1080ならば-video_size hd1080とも書ける。

録画領域を表示するには-show_region 1

$ ffmpeg -show_region 1 -vaapi_device /dev/dri/renderD128 -f x11grab -framerate 30 -video_size hd1080 -i $DISPLAY -vf 'format=nv12,hwupload' -c:v h264_vaapi -profile 578 -preset ultrafast -qp 24 -f alsa -i pulse -c:a aac -b:a 192k outfile.mp4

NVENCだとmkvにもできるので音声はFLACやOpusで撮ることもできるのだけど、AMDGPU VA-APIはmp4だけ

使ってみた感想としては、QSVと違ってCPUがあくのは良いけれど、R7の速度自体がCPUと大差ない(libx264でやったのと同程度)であるため、ちょっと微妙かもしれない。 A10でもスクリーンキャスティングしながら配信みたいなことができるというメリットはあるけれども。

(Linuxにおける) シャットダウンとリブートの違い

Twitterで、「Linuxでもシャットダウンとリブートは違うよ」という話をしたら、若干の反響があったので、軽く解説。

なお、私はこのあたりのことはそこまで詳しくないので、詳しい解説をすると多分間違えることからほどほどにしておく。

Linux上の仕組み

実は私が行っているのはLinux上でどうこうということではなかったりするのだけど、けれど若干違いはある。

Systemdの場合はsystemd-reboot.service

After=shutdown.target umount.target final.target

となっており、reboot.target

After=systemd-reboot.service

となっている。 でもって、じゃあsystemd-reboot.serviceはなにをしているかというと…

ExecStart=/usr/bin/systemctl --force reboot

そう、再起動はSystemdの場合組み込みである。

shutdownのほうは割と単純で、Conflicts=shutdown.targetBefore=shutdown.targetがあるので色々終了処理を行う。 shutdown.targetはそれだけの存在で、shutdown.servicesystemd-shutdown.serviceはない。

シャットダウン自体はSystemdに組み込みで存在し、reboot同様systemctl shutdownで良い。

ただ少なくとも、rebootとshutdownが分けられている、というのはわかる。

ハードウェア的に

ここからが私が言っていた話になる。

実際に再起動してみるとわかると思うのだが、普通のパソコンでは再起動しても電源が切れることはない。 そして、電源を入れるのと比べて速く立ち上がる。

ワークステーションや、一部の業務用PC(法人向けのモデル)だと再起動時に電源を切ったりするのだが。

そもそもシャットダウンした時点でプロセスはほとんど残っていないのだから、OS側から「電源を切ったら起動する」のような制御をすることはできない。 当然ながらこれはファームウェア的な動作であり、ファームウェア的にシャットダウンの状態とリブートの状態を分けていることがわかる。

一般的には再起動時はPOSTが省略される。 そのため、デバイス認識がバグっている状態(例えば接続されているキーボードが認識されていないとか)では再起動では修復されなかったりする。

ただし、BIOS/UEFI設定に言ってsave changesした場合は(通常は変更があったかどうかにかかわらず)POSTからやり直すようになっている。

電源を切るかどうかについては、メモリ(DIMMに限らず)に影響を及ぼすことから、違いがでる、かもしれない。

英語で、ものすごーーーーく詳しい説明を見つけたのだけど、再度見つけることができず掲載できない。

「LinuxにはIntel*Nvidia」は終わり、時代はAMDに

安定してきたAMD Linux

LinuxにおいてはCPUもビデオカードもAMDは非常に安定性がなく、「LinuxではAMDはリスキー、IntelとNvidiaが鉄板」という時代が非常に長かった。

これはWindowsにおいてもそんなものだとは言えるが、どちらかといえば性能とか好みとか思想の問題であり、AMDだと困るという要素は少なかったのだが、Linuxにおいては動作安定性という意味でもAMDは避けたい、という状況があった。

大きな問題としてはCatalystドライバのデキの悪さがあった。プロプライエタリドライバーとしてもNvidiaよりも後にサポートされてきたCatalyst(flgrx)ドライバーだが、様々な問題が発生していた。私が利用している限りでもXサーバーのフリーズ、マウスカーソルの文字化け、ティアリング、画面化け、X再起動の失敗、などなど枚挙に暇がない。

AMDがLinuxに力を入れるという選言をしたのは、Linux 4.6の頃であったと思う。 そしてAMDGPUドライバーが誕生したわけだが、実際安定性は高いものの性能はいまひとつであった。

そこから3年ほどが経過している。 Linux 4.18ではAMDGPUの改善が進んだ。Vega 20や、Intel Kabylake-Gプロセッサ(IntelのプロセッサにAMDのビデオカードが内蔵されている!!)といったデバイスサポートが主だが、AMDGPUドライバーそのものの改善も結構手を入れていた印象だ。 その結果AMDGPUドライバーは4.18の初期には性能が従来よりも低下していた(!)

AMD APU(Godavari)マシンに4.18を導入してみて驚いた。 アップデートごとにどんどんよくなっていたAMD環境だが、4.18は明らかに描画がスムーズになった。 ビデオ性能に関していえばNvidiaのほうが(私の手持ちでは)良いのだが、結局のところLinux利用の上での快適性は画面のちらつきや、フリーズの有無、あるいはビデオ再生に支障があるか…といったことに左右される。

結果的に性能は圧倒的に低いのだが、そうしたエラーが少ないAMDGPU環境が非常に快適に感じられてしまうのだ。 実際、ビデオ再生に関してもLinux 3.17あたりの再生と比べて明らかに快適になった。

現状、ビデオドライバーから見れば「AMDGPU > Intel > nouveau > nvidia」という状況になっている。 本当に力を入れてきたAMDドライバーの成果が、「とりあえずIntel安牌」という状況を靴替えしている。Nouveauもそれなりに安定しているのだが、基本的にはメーカー協力のない、リバースエンジニアリングの成果物であること、またNvidiaはLinuxドライバーにあまり力を入れていないことからこの滋養今日が生まれているのだろう。

実際にPhoronixのベンチマークを見るとRX580がGTX1060よりも良い結果を出していたりする。 (まぁ、一方でVega56がGTX1070に全然勝てていなかったりするのでドライバーの優劣を反映しているようにも見えないが)

現状、Nvidiaドライバーでの問題と言えば

  • Google Chromeはウィンドウ移動時にマルチディスプレイでは座標がずれる
  • 画面が激しく点滅することがある
  • ffmpegでの録画時にちらつく。Allow Flippingを無効にしてもまだちらつく
  • Wineが条件によって問題を起こす (nouveauでも)

あたりである。このほか、Xサーバーのrespawnの失敗、Blink系ブラウザにおいてコンソールと行き来したり状況によってはフリーズする、デスクトップエフェクトの反応が悪い、などがある。

そしてCPUもしっかりとパフォーマンスを発揮するようになっていて、4.18においてはXeon Silver 4114のpowersave governorよりもA10-7870KのほうがChromiumで高速に描画できる(シングルスレッド性能の差だ)。

性能と選択肢の改善

Ryzenによって向上した選択価値

A10-7870Kシステムを組んだときには随分と後悔したものだが、Linux側の改善によって随分と快適なシステムに進化してきた。 従来のAMD APUは使い勝手は良いもののその性能は悲しいほどしょうもなかった。

A10はAMD APUでも上級グレードだが、その性能はIntel Core i3に及ばない。 PentiumやCeleronよりは良いのだが、現在はPentium Goldに抜かれてしまっているほどだ。

AMDはAシリーズの上はゲーム向けとしてビデオカードを内蔵しないFXシリーズをラインナップしていた。 だかいくらなんでも「Aシリーズの上はゲーム用」というのはちょっと乱暴である。一般用途で確実に十分であるほどにはA10は性能はよくない(ただし、恐らく十分である程度には高い)。

ところが、現在はRyzen Gシリーズがある。 これは従来のAPU (Aシリーズ)を置き換える新しいAPUである。

少し複雑なので説明すると、第二世代Ryzenには、第一世代Ryzenと同じくビデオカードを持たないモデル、 つまり従来のFXと同じ「ゲーマー向け高性能プロセッサ」という位置づけだった。

しかし、Ryzen3/5/7というネーミングの通り、Core i3/5/7の直接的なライバルとなるラインナップであり、 Core i3をゲーマー向けプロセッサとするのは無理がある通り、AMDも考えを改めた。 さらにいえば、Aシリーズの不評っぷり(性能がとても低く、そのくせ消費電力は大きい)とRyzenの好評っぷり(いままでのAMDが嘘のようだ)を踏まえてもAシリーズを継続させていくよりさっさと仕舞にしたほうが良いと考えたのだろう。 結果RyzenシリーズはAMDの主力プロセッサシリーズへと転身した。

しかし、それはそれでややこしいことになった。 AMDの場合、Ryzenにはビデオカードを内蔵するGシリーズと、そうでないSTD/Xシリーズの2系統がある。 さすがにゲーマーはRyzen3を使わないと悟ったのか、Ryzen3はGのみ、一方ゲーマーでもなければRyzen7は使わないだろうと考えているらしくRyzen7はSTD/Xのみ、一方Ryzen5は両方ある。1

単にビデオカードの有無かというとそんなことはなく、Passmarkで見てみると

CPU Score Intel rival Rival score
Ryzen 7 2700X 16882 Core i7-8700K 15975
Ryzen 7 2700 15087 Core i7-8700 15217
Ryzen 5 2600X 14448 Core i5-8600K 12805
Ryzen 5 2600 13523
Ryzen 5 2400G 9264 Core i5-8500 12060
Ryzen 5 2400GE 8513 Core i5-8400T 9672
Ryzen 3 2200G 7331 Core i3-8100 8086
Ryzen 3 2200GE 7229 Core i3-8100T 7532
Ryzen 3 2300U 7172

RyzenのGEやU、またIntelのH/T/Uについては後述する。

また、Ryzen Proというのはセキュリティの追加機能があるものである。

このようにRyzen5 2400GはRyzen5 2600よりも下位グレードという扱いになっていて、Core i5と勝負できるのはビデオカードなしモデル、ということになっている。お値段的にもちょこっと2400Gのほうが安い。

この中でRyzen5 2400G及びRyzen3 2200Gは非常に魅力的である。

そもそもAPUという発想は悪くなかった。「別にそんなにCPUパワーはいらないだろうけど、動画見たり、たまにはゲームもするだろうし、ビデオ性能はそれなりに高いほうがいいだろう?」という考え方にはとても同意できたのだ。だが、Aシリーズは「そんなにない」というか「あまりにもない」というのが現実であって机上の空論に終わっていたのだ。

ざっくり、RyzenになってAPUは「2倍のパワーになった」と考えれば良い。さすがに2倍も速いと話は変わってくる。 HEVCのエンコードにも対応した最新ビデオカード(後述するvegaである)を搭載しながら、2倍速くなったAPUは普通の人にとって本当にいいバランスになっている。

普通の作業にはRyzen5 2400Gのパワーは十分だし、軽作業ならRyzen3 2200Gは悪くない。そしてビデオ性能のほうはIntelはいささか不足気味だ。 大きなポイントとしては、IntelのQSVはCPUパワーをかなり使う。これは動画見ながら作業することは考えにくいラップトップではあまり気にならないが、デスクトップの場合、特にマルチディスプレイ環境では足かせになる。 また、コンシュマークラスのIntel CPUの場合依然として「動画エンコード中は他の作業が難しい」という状況が発生する。 人によっては些細な違いに思えるかもしれないが、実際は使い心地に影響を及ぼす可能性がある。

また、自作する場合はAMDのマザーボードは非常に高機能なものや安価なものが揃うという点も見逃せない。 実際、私のA10システムは豊富なUSBサポート、8つのSATA、S/SPIF端子を持つオーディオなど豊富な機能によってデスクトップユースで一線級ではなくなったとしても様々な使い途が残る。

強力なシステムも組めるようになった

Core iと比べたとき必ずしもRyzenは魅力的なわけではないが、AMDのプロセッサの性能が大幅に上がったために、高性能が求められる局面でもAMDという選択肢が加わった、という点が大きい。

さらにThreadripperに至っては文句なしに強力である。

だが、CPUに関してはあからさまにLinuxにおける利があるわけではない。 ビデオカードの話をしよう。

現在のAMDのビデオカードラインナップはちょっと複雑で、やや古いRX 400シリーズはPolaris10, メインストリームのRX500シリーズはPolaris20、ハイクラスのRX VegaはVegaと設計が異なる。 さらにメインストリームはVegaにならずPolaris30になり、ゲーム用はVega20になってからメインストリームがNaviに、ハイクラスはNavi20になる、と噂されている。 (つまり、Navi登場までの間をメインストリームはPolaris、ハイクラスはVegaのままプロセス微細化されたものでつなぐらしい)

ところがAPUに搭載されているのはVega。Vegaのほうが新しい。取り残されているRX500がすごくいまいちに思えてしまう。

しかしここには罠があって、Linuxでは(Windowsと比べても)性能的にVegaがいまいち振るわず、Polarisのほうが良い結果を残している。 AMDGPUドライバが新しいVegaの性能を発揮できていないのかもしれない。

ともかく、Ryzen 7 2700X + Radeon RX580, Ryzen Threadripper 2950X + Radeon RX Vega 56, Ryzen Threadripper 2990WX + Radeon Pro WX 8200のような強力なシステムを組めるようになったわけだ。

Radeonの重大な欠点だったHEVCエンコードも対応しており、NVENCほどではないもののVCE/VA-APIでかなり高速にエンコードができる。

APUによる省コストなシステムだけでなく、パワーを必要とするシステムにおいてRadeonを使う、ということが現実的になったのだ。 もちろん、これはIntelプロセッサと組み合わせても構わない。

省電力システム

AMDはいつの時代も電気を食うものだった。 さすがにそれが終わりを告げた、とまでは言わないが、Intelの高性能プロセッサがTDPを越える電気を使ってしまう中、 Threadripperは実質的なワットパフォーマンスでの逆転を見せた。

そんな新時代のAMDとして推したいのがRyzen 5 2400GEである。

Intelの場合H(省電力), T(超省電力), U(超低消費電力)とラインナップされていたりするのだけど、AMDの場合GEはT相当と考えてよさそうだ。

2400GもcTDPで35W/45W/65Wということらしいけれど、そんなややこしいことは置いといて、2400GEは35Wである。 35Wだけどベースクロックは3.2GHz。ここらへんのCPUは割と容赦なく電気を使うので、まったり処理してほしい低消費電力システム(特にホームサーバー)ではすごく便利だ。

それだったらIntelのTでも良さそうに思えるけれども、前述のようにビデオカードが強力である。 ホームサーバーとして使うなら動画処理性能は重要な項目となりえるし、デスクトップとして使うなら描画環境は重要であり、AMDのほうが快適である。

もちろん、これは「Linuxで使うラップトップでAMD優位」という状況でもあると言える。 (もっとも、絶対的な消費電力の問題があるから話はそう簡単ではなくなってしまうが)


  1. この考えはとても正しい。多くの人はCore i3で満足できるが、ゲーマーはCore i3では足りない。一方、多くの人はCore i7を必要としていない。

Mimir Yokohamaで続く改修、力を注ぐ

2018年8月5日、Mimir Yokohamaのソースリポジトリにはじめてのタグ、5.0が打たれた。

なぜはじめてのタグなのに5.0だったのか。

これは、Aki SI&Eのプロトタイプを1.0, Aki SIEのウェブサイトを2.0, Mimri YokohamaのWordPressを3.0, 現在のウェブサイトになったときを4.0とカウントしたものだ。

つまり、はじまって以来の、同一システムのままのバージョンアップとなった。

しかもこのタイミングである。 先日、大幅な編成変更と、いいね機能、コメント機能の追加を行った。 これで新しい船出だというタグではない。かといって同バージョン最終仕様としてのタグでもない。

これから次々とアップデートが予定されている。 その中での一区切りだった。

13年積み上げてきたものとは

PureBuiler Simplyの原型となっているのは2005年のACCS1である。

もうブログが流行り始めていた頃だったが、既に「事前生成戦略」に関するイメージはあった。 ブログを避けた理由は、一連の流れを持つ記事群を拾いにくくなること、そして時間とともに消えてしまうことだった。

「普遍的な内容を、きちんと分類して読みやすいように提供したい」と考えたわけだ。

様々な機能、様々なアイディアがあった。 実装されたものもあるし、実装されなかったものもある。 言語もPerl, PHP, Zsh, Rubyと変わってきた。 このような変遷をたどっているのはEQAIとこれだけで、まさに私のライフワークであり、また成長の軌跡でもあった。

この中でこだわってきたものもある。

例えば、デザイン性を保ったまま軽量・高速なウェブサイトを構築すること、可能な限り高いアクセシビリティを提供すること(環境や回線の違い、身体的ハンディキャップなどで差別しないこと)などもそうだ。 意味あるコンテンツを、読みやすい形で提供する、というのもある。

ACCSが追い求めてきた機能は次のようなものだった。

  • カテゴリで分類されて探しやすいインデックス
  • 検索機能
  • 意思表示機能 (コメント、と考えていることが多かった)
  • 連続した記事のページめくり
  • 要約の先読み
  • インライン用語集
  • prev, next, glossary, index, description情報を持たせる

PureBuilder Simplyは当初、Mimir YokohamaのWordPressページで提供されている全機能を提供する、ということを目標としていた。 これについては既に達成されている。そのために、従来のPureBuilderにはなかったタグ機能なども追加された。

「いいね機能」「コメント機能」はWordPressに完全な意味で標準であるものではないのだが、事実上付属するようなもの(特にコメント機能は)なので、これを追加したことで、事実上「WordPressを置き換える」というミッションは完遂した。

だが、同時に既にWordPressにはない機能の搭載もはじまっていた。 用語集機能はWordPressではなく、PureBuilderの伝統に由来する。そう、ACCSが目指していたものを達成する、という次のミッションに向かいはじめたのだ。

そこでつけられたのが5.0タグだった。

用語集機能

用語集機能という発想のスタート地点は、私が使っていたWindows 98SEマシンに搭載されていたインライン翻訳ソフトだった。

カーソルを載せるだけでその単語を翻訳してくれる、というソフトウェアは今持ってそれ以上のユーザービリティを提供するものはない。

「カーソルを載せたらわからない言葉を教えてくれる」というのは最高に便利だと思ったのだ。 現在はニコニコやはてなが似たような機能を提供しているが、あれはページが変遷してしまうため私からすれば理想的ではない。 どらちかといえばWikiに搭載されているインライン展開のほうがずっと理想的だ。

この機能は

  • 表示後にJavaScriptでtreatする
  • 生成時にHTMLを置き換える形で組み込む
  • ソースドキュメントを改変してから生成する

という3つのパターンを行ったり来たりしている。

PureBuilder SimplyではPost Plugins/Pre Pluginsの構造からこの3つとも選択肢として取ることができる。 Mimir YokohamaではPost PluginによるHTML置換え方式を取っている。

このあたりは試行錯誤の成果といえるだろう。 用語集ページも含めてYAMLの辞書ファイルから生成しており、文書に対して特別な処理は必要ない。

次の記事、前の記事

ACCSで最も苦戦したのがこの機能だ。

この解決については何度か言及しているが、今は前後関係をメタ情報として書く、という仕様になっている。

解決方法としては後退しているように見えるが、前後関係の自動解決はファイル名なり、もしくはなんらかのヒントなりを厳密に管理する必要があり、結構バグりやすいということを経験したのだ。

複雑な置換えやユーザーの管理によってバグを発生しうるようなものであるならばメタ情報をユーザー自身が書くべきだ、という割り切りは、これまでの歴史の中で手にしたバランス感覚である。

実のところ今の構成では前後を自動化することは難しくない。 だが、ユーザーがそれを守ってくれることを期待すべきではないだろう。

Post pluginsはページ生成が終わってから実行されるが、これは「他の記事の情報を取得できるようにする必要がある」からであり、 環境変数$pbsimply_indexesという形でデータベースのパスが渡っていることから

のようにして取得できるし、 連番に限るのであればもっと簡単に

とできる。 ちなみに、ディレクトリを認識させる方法は最新のコミットで環境変数$pbsimply_subdirに含まれるようになった。

このように「できるけれど、あえて手書き」だ。 これは、問題を簡単にするためと、この処理をPandocテンプレートを通じて行いたいためだ。 Pre Pluginsを使えばできるが、かなり複雑なことをすることになるため避けている。

意思表示機能

過去には「コメントを直接にHTMLファイル化し、objectで読ませる」ということをしていたこともある。

表示するかどうかを別として、コメント機能はそのときとあまり変わっていない。 表示させるために必要な部分を削ってシンプルになったくらいだ。

このような機能は本質的な部分は極めて簡単に書けることはこれまでの経験によって証明されている。 どの程度正当性を検証する必要があるかという点がwebアプリケーションの分量になる。

要約の先読み

まずは要約を入れる

いよいよ今回のハイライトだ。

descriptionへの対応自体は最初のリリース時点で

という記述があり、対応はちゃんとしていた。 だが、「書くのが面倒」「書いてもあまり意味がない」ということで放置していた。

「descriptionの先読み」は今まで実装計画には入っていたが、実装されたことはなかった。 そもそもdescriptionってSEOのために入れられているくらいで、「descriptionを読ませる」という発想はあまりない。

Firefoxだとこんなふうにブックマークのプロパティを表示するか、ブラウジングライブラリー上で詳細表示にするとdescriptionが表示されたりするのだが、これを見たことがある人という人は地球上に5桁いないのではないだろうか。

Firefoxのブックマークの詳細

だがdescriptionは入れたいと思っていたし、それを活用したいと思っていた。

そもそもの発端はトップページのレイアウト更新で、最新の更新記事と要約を(ニュースとは別に)表示したい、ということだった。 「どうせ記事の要約書くんだったらdescriptionに入れようよ」ということだ。

実はAtomフィードもスタンバイしている。

要約を見える形に

だが、これだけではおもしろくない。どうせ要約を表示するのならばぜひともユーザーに見える形にしたい。

私の文章は基本的に長いので(体系的でない短い文章に価値を感じていない)、読むのがしんどい人もいるだろう。 読むかどうか決めるために要約は重要だ。

要約を見たいタイミングとはいつだろう? やはり記事を読み始める前だろう。ならば本文前に

とかやってやればいいし、そのほうが効果的なのかもしれないが、既に「文書情報」という項目があることを考えるとちょっといただけない。

そこで文書情報に追加した上で「記事タイトルをクリックすると文書情報にジャンプする」という仕様にした。

これはヘルプページにも書いてあるけれども、誰も気づかなそうだ…

もうひとつ、利用者は多くなさそうだが、カテゴリインデックスがある。 ACCSとしてはこれが中心であり、ぜひとも使って欲しい機能だ。 世の中、情報を整頓するということに怠けすぎて、検索が全てになってしまっているので、使われていないような気もするけれど…

しかし私の意図としてはこのようなインデックスを活用してほしいというのがあるし、やはりタイトルだけではわかりにくい。 かといって変遷するとだるいので、変遷せずにインデックス上で要約を確認できると便利だ。

これはタイトルで関心をそそられた後の二次的な情報であり、通常は一覧性が高いほうがいい。 というわけで、ツールチップにしてみた。

PureBuilder Simply ACCS上でDescriptionを扱う

単純には記事タイトルにtitleで入れてあるため、ロールオーバーツールチップとして表示される。 だが、スマホだとこれが効かないので、補助的に“📖?”と表示して、これをタップすればツールチップが表示されるようにしてみた。 全く標準的でないインターフェイスなので、あまり気づいてもらえないような気もするけれど…

PBS ACCS用ツールチップ実装

何度見てもJavaScriptの複数代入が慣れない。 慣れればみやすそうだけども。

世の中的には割と珍しいDOM操作をしているが、これはelementに対してイベントリスナを設定するためで、innerHTMLだと二度手間になる。 基本的にやっていることは「記事部分 > リスト全体 > リンク」と絞り込んでいって要素を作成して追加する、という手順だ。 末っ子要素を追加するとき(今の要素の親要素の最後の子要素として追加する)はelement.parentNode.appendChildという手順は覚えておいてもいいかもしれない。

glosarryと共通のコードがライブラリとして読まれるようになっている。ライブラリはdeferだがasyncではない。

900pxを堺にしているのは、「サイドカラムがあるのであれば表示領域は少なくとも右側にサイドカラム幅はあるが、シングルカラムになるとそうではない」からだ。(このページのシングルカラム境界は800pxである)

機能チェックしているが、document.addEventListenerできないブラウザでJavaScriptに対応しているものはあまり残っていないだろうし、あっとしても単純にイベントリスナー設定時にエラーになるので放置してもいいかもしれない。 ただし、間違って複数回ライブラリが読まれたときのためにArt.tooltipはしておかないとイベントリスナが複数設定されてしまう。

PureBuilder Simplyはうまくいっている

PureBuilder Simplyがここまでうまくいっている理由としては、やはりPandocの強力さがなによりだろう。

PureBuilder SimplyはPandocが持っている機能をちょっと拡張する…という考え方をしている。 今までドキュメントジェネレーター自体を制作していた(PureDoc)ことと比べると問題はかなり簡単になっている。

Pandocの動作は必ずしも簡潔ではなく、自分で実装するのであればドキュメントジェネレーターにここまでの機能をもたせることはないだろう。 だが、Pandocがある以上はPandocを使いたい。

もしPandocがなければdocutilsを拡張することを考えただろうが、その場合はPureBuilder Simplyは今のように良いツールにはなっていなかっただろう。

PureBuilder Simplyが今ほど素晴らしいツールになったのは、Pandocがあったからこそだ。

Mimir Yokohamaに対して行われている様々な拡張は今の所PureBuilder Simplyに対して適用されていない。 これは、PureBuilder Simplyが生成するものに対する機能ではなく、Mimir Yokohama固有の、そしてテンプレートとCSSによるものだからだ。

だが、いくらかでも一般化してPureBuilder Simplyに還元していければと思っている。 PureBuilder Simplyのエコシステムの充実は普及には不可欠だろうから。