4790KのPCでWindows11する。

現在のメインPCはCore i9-9900Kなので、すでにWindows11にアップグレード済なのですが、以前使っていた2台のPCはどちらもCore i7-4790Kで、Windows11の対象外になってしまっています。

2015年に購入したものですが、4790Kは今でも十分に使える能力は持っているので、このまま置いておくのはもったいない。ということでなんとかWindows11にできないかとやってみました。

まず、マイクロソフトのWindows 11をインストールする方法のページを参考にレジストリを追加します。こちら(マイナビニュース)にも同様の記事があります。
reg add HKLM\SYSTEM\Setup\MoSetup /v AllowUpgradesWithUnsupportedTPMOrCPU /t REG_DWORD /d 1 /f
を管理者用コマンドプロンプトで実行します。これでCPUがサポート外でもアップグレードが可能になります。

ところが、使用しているマザーボードがAsrock Z97 Extreme 4で、これはTPM2.0に対応していません。これだけだとWindows11セットアップではねられてしまいます。

CPUのほうはこれでスキップできましたが、どうにもTPM2.0のところで引っかかってしまい、先に進みませんでした。

そこで、こうなったらTPM2.0モジュールを購入しようと決心し、ダメでもともと、一番安そうなところを探してみました。Asrockが出しているTPMモジュールが購入できればよいのですが、これがなんと1万円以上しているのです。そもそも出荷数が少ないのか、それともWin11特需でなくなっているのかはわかりませんが、そこまでお金は出せません。このページによれば、Nuvoton NPCT650またはInfineon SLB9665なら使えそうです。

Amazonで購入したのはこちら。Extreme 4のマニュアルを見ればわかる通り、TPMモジュール用ヘッダは18ピンで13ピンが抜けているタイプです。AmazonのページにはType AからType Iまで9種類がありますが、Type Cが当てはまります。もちろん信号名なども照らし合わせて確認しています。注文すると品物は上海から発送されましたが、2週間ほどで手元に届きました。ちなみにチップはInfineon SLB9665TT20です。
ということで早速PCにセットして、起動してみたのですが…。
BIOSのUEFIでIntel Platform Trust Technologyの項目が出てきません。

これもよく調べてみるとBIOSで対応していないようで、最新の2.60でもダメでした。ところが下の方にベータBIOSがあり、そこにある2.60Aで「Support TPM 2.0」とあります。ということで早速Instant FlashでBIOSをアップデートし、TPMモジュールを接続してみました。

…が、それでも出てきません。Win+Rキーで「tpm.msc」と入力してTPMの管理パネルを開いても、モジュールが見つからないというメッセージです。

ここでデバイスマネージャーを見ると不明なデバイスが増えていて、よくよく見てみるとこれはTPMモジュールではなくIntel Smart Connect Technologyデバイスでした。これをBIOSでDisableしてやると、UEFIのAdvancedタブのところにIntel Platform Trust Technology関係の項目が増えていました。

その状態でWindows10を起動し、「tpm.msc」を開いてみると…。
認識されました。これなら勝つる!
ちなみにMBRからGPTへの変更はWindows 11のための準備を整える。の手順ですでに終わっています。
そのままWindows 11のセットアッププログラムを実行してみると…。
おお!
どっこいしょ!
そらきた!
ということで、ずんずん進み、最終的にインストールは完了しました。
CPUはCore i7-4790Kで、OSはWindows 11 Proです。

FFmpeg 5.0をコンパイルしてみる。

ビデオファイルをいじったりエンコードしたり加工したりするのに必須なffmpegの5.0がリリースされたので、コンパイルしてみました。

記事はこちら。「FFmpeg 5.0」が公開 ~大規模なAPIの変更を実施した長期サポート(LTS)リリース

環境はWSL2上にインストールされたArchLinuxを使います。別にUbuntuとか他のディストロでも問題ないと思いますが、うちはArchしかないので…。

まず、ffmpeg-windows-build-helperをcloneします。

$ git clone https://github.com/rdp/ffmpeg-windows-build-helpers

そしたらそのディレクトリに移動します。

$ cd ffmpeg-windows-build-helpers

指定オプションの意味は、

$ ./cross_compile_ffmpeg.sh -h

すれば出てきます。英語のみですけど。

でもってビルドします。

$ ./cross_compile_ffmpeg.sh --build-ffmpeg-shared=y --ffmpeg-git-checkout-version=n5.0 --fdk-aac-git-checkout-version=v2.0.2 --gcc-cpu-count=8 --disable-nonfree=n --build-intel-qsv=y --build-lsw=y --compiler-flavors=win64

すると怒られます。

    windows WSL detected: you must first disable 'binfmt' by running this
        sudo bash -c 'echo 0 > /proc/sys/fs/binfmt_misc/WSLInterop'
        then try again

言われたとおりにします。

$ sudo bash -c 'echo 0 > /proc/sys/fs/binfmt_misc/WSLInterop'

再度ビルドします。

$ ./cross_compile_ffmpeg.sh --build-ffmpeg-shared=y --ffmpeg-git-checkout-version=n5.0 --fdk-aac-git-checkout-version=v2.0.2 --gcc-cpu-count=8 --disable-nonfree=n --build-intel-qsv=y --build-lsw=y --compiler-flavors=win64

しばらく待ちます。
また怒られます。
仕方ないので、cross_compile_ffmpeg.shを編集し、

    config_options+=--enable-libsvthevc

をコメントアウトして、--enable-libbluray --enable-fontconfig --enable-libfreetypeを削除します。たぶんこれは字幕に必要だからだと思いますが、うちでは不要なので問題なしです。
再度ビルドします。
また怒られました・・・QSV関係なので、これはコマンドラインオプションから--build-intel-qsv=yを削除します。

再度ビルドします。

すると、

  Done! You will find 64-bit shared non-redistributable binaries in
  /home/kats/work/ffmpeg-windows-build-helpers/sandbox/win64/ffmpeg_git_with_fdk_aac_n5.0_shared/bin
  

なので、次のようにしてアーカイブし、mntしてるWindowsのフォルダに放り込みます。

  $ cd /home/kats/work/ffmpeg-windows-build-helpers/sandbox/win64/ffmpeg_git_with_fdk_aac_n5.0_shared
  $ 7z a ffmpeg_with_fdk_aac_n5.0_share.7z bin doc include lib presets LICENSE.md README.md
  $ cp ffmpeg_with_fdk_aac_n5.0_share.7z /mnt/c/Users/kats/work
  

でもって、パスの通ったところに展開すれば完了です。

MP4ファイルを連結する。

2つあるいは3つのMP4ファイルを連結する必要が出てきました。たとえばビデオカメラで撮影した2本の動画だったり、ごにょごにょだったり、もにょもにょだったりしますが。


テキストファイルなどなら、コマンドプロンプトからcopy a.txt+b.txt c.txtでできますが、MP4ファイルの場合にはコンテナの中にビデオストリームとオーディオストリームが格納されていて、撮影情報とかメモとかいろんなタグが含まれていて、そのまま連結してもうまくいきません。

ビデオ編集には、PegasysのTMPGEnc MPEG Smart Renderer5(6にするメリットが今のところないので)を使っていますが、これで連結出力すると連結部分があまり良くない画質で再エンコードされてしまいます。いろいろとオプションなどを見てみたのですが、再エンコードせずに連結することはできないようです。
AviutlでMP4Pluginを使用すると、追加ファイルを読み込んだ上でMP4エクスポートすればいい、という記事も見つかりましたが、連結部分で止まってしまい、うまくいきませんでした。

ああ、そういえばffmpegをインストールしてたんだっけ、と、困ったときのffmpeg頼りで調べてみたら、できる方法がありました。
ffmpegのWikiよりConcatenate。 簡単に言えば二通りの方法があります。

リストファイルを作って作業する

連結したいMP4ファイルのリストを作成して、それをffmpegに処理させます。

以下のようなファイルを作ります。
file dir/input1.mp4
file dir/input2.mp4
file dir/input3.mp4
その上で、以下のコマンドで連結します。
ffmpeg -f concat -c copy -i listfile.lst outfile.mp4
もしもファイル名にスペースを含むようなら、''(シングルクォーテーション)でくくります。""(ダブルクォーテーション)ではエラーになります。

この方法では、中間ファイルを作らずに直接出力ファイルを作りますが、リストファイルを作成する手間がかかります。

中間ファイルを経由してmuxする

連結したいMP4ファイルからストリームを抜き出して、それを連結して新しいコンテナに収めます。

この方法では、エンコーダが異なったりFPSが異なったりフレームサイズが異なった場合には、取り出したストリームをエンコードし直すことで連結できる可能性があります。

ストリームがH264ビデオストリームの場合:
ffmpeg -i input1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts input1.ts
ffmpeg -i input2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts input2.ts
ffmpeg -i "concat:input1.ts|input2.ts" -c copy -bsf:a aac_adtstoasc output.mp4
上の2行のコマンドでそれぞれH264ストリームを抜き出して input1.ts、input2.ts という中間ファイルを作成します。

ストリームがHEVC(H265)の場合:
ffmpeg -i input1.mp4 -c copy -bsf:v hevc_mp4toannexb -f mpegts input1.ts
ffmpeg -i input2.mp4 -c copy -bsf:v hevc_mp4toannexb -f mpegts input2.ts
ffmpeg -i "concat:input1.ts|input2.ts" -c copy -bsf:a aac_adtstoasc output.mp4
コーデックが異なったりする場合には再エンコードが必要になるので、その分時間がかかりますが、詳細はこちらに。 ちなみにうちで使用しているffmpegはこちらからダウンロードしています。

Windows 11のための準備を整える。

Windows11のTPM。ではTPMについてちょっと触れましたが、Core i7-4990KではTPM2.0に対応していないので、TPM-SPIというようなTPMモジュールをインストールすれば…と思ったんですが、そもそも第4世代CPUはサポート対象外で、さらにノートPCで搭載している Core i7-6700HQ ではTPM2.0に対応してるのにやっぱりサポート対象外で。
今後サポートCPUが追加されるのかどうかはわかりませんが、現状ではWindows 11のインストーラ自体がCPUチェックで「インストールできません」と言ってきます。

前回の記事ではBIOS設定の Intel(R) Platform Trust Technology は有効化したのですが、PC正常性チェック(PC Health Check)プログラムまでは走らせていませんでした。そこで走らせてみたところ…。


と、セキュアブートをサポートしていないとだめです、と言われてしまいました。

そこでセキュアブートについても調べてみたのですが、これを有効化するためにはそもそもMBRパーティションではだめで、GPT(GUID Partition Table)に変換しないといけないようです。
うちのメインPCでは、mSATA SSDに換装したときに「起動ドライブは2TB未満だからMBRでいいか」と判断してMBRパーティションにしていました。

ということで、Windows 11にアップグレードするためには、起動ドライブをMBRからGPTに変換しないといけません。

変換方法を調べると、サードパーティのパーティションツールが色々出てきますが、どれもフリー版ではパーティションをMBRからGPTに変換する機能は利用できないようです。
これを見越したのかどうか、幸いにも Windows 10 Creators Update 1703以降では、MBR2GPT.exeというユーティリティプログラムが搭載されたようです。これを使うと、サードパーティツールを使わなくてもデータを失わずにGPTに変換できるようです。
まず、「ディスクの管理」で起動ドライブを確認します。

Cドライブはディスク4になります。ここで、ディスク4の上で右クリック→「プロパティ」で「ボリューム」タブを見ると、パーティションのスタイルが「レガシー」となっています。これをGPTに変更する必要があります。

別の方法として、コマンドプロンプトを管理者モードで開き、diskpartでも確認します。
C:\WINDOWS\system32# diskpart

Microsoft DiskPart バージョン 10.0.19041.964

Copyright (C) Microsoft Corporation.
コンピューター: UZI

DISKPART> list disk

  ディスク      状態           サイズ   空き   ダイナ GPT
  ###                                          ミック
  ------------  -------------  -------  -------  ---  ---
  ディスク 0    オンライン          7452 GB  1024 KB        *
  ディスク 1    オンライン           931 GB  1024 KB        *
  ディスク 2    オンライン          5589 GB      0 B        *
  ディスク 3    オンライン          5589 GB  1024 KB        *
  ディスク 4    オンライン           476 GB  1024 KB

DISKPART> exit

DiskPart を終了しています...

ディスク4のGPTの欄に "*" がないのがわかります。

次に変換を実行する前に、ディスクの検証を行います。
C:\WINDOWS\system32# mbr2gpt /validate /disk:4 /allowfullos
MBR2GPT: Attempting to validate disk 4
MBR2GPT: Retrieving layout of disk
MBR2GPT: Validating layout, disk sector size is: 512 bytes
MBR2GPT: Validation completed successfully

"/allowfullos"オプションを指定しないとエラーになりますが、正常終了したようです。

ということでいよいよ変換です。失敗するとディスクが飛ぶんじゃないかと心配もありますが、やってしまいます。
C:\WINDOWS\system32# mbr2gpt /convert /disk:4
ERROR: MBR2GPT can only be used from the Windows Preinstallation Environment. Use /allowFullOS to override.

C:\WINDOWS\system32# mbr2gpt /convert /disk:4 /allowfullos

MBR2GPT will now attempt to convert disk 4.
If conversion is successful the disk can only be booted in GPT mode.
These changes cannot be undone!

MBR2GPT: Attempting to convert disk 4
MBR2GPT: Retrieving layout of disk
MBR2GPT: Validating layout, disk sector size is: 512 bytes
MBR2GPT: Trying to shrink the OS partition
MBR2GPT: Creating the EFI system partition
MBR2GPT: Installing the new boot files
MBR2GPT: Performing the layout conversion
MBR2GPT: Migrating default boot entry
MBR2GPT: Adding recovery boot entry
MBR2GPT: Fixing drive letter mapping
MBR2GPT: Conversion completed successfully
Call WinReReapir to repair WinRE
MBR2GPT: Failed to update ReAgent.xml, please try to  manually disable and enable WinRE.
MBR2GPT: Before the new system can boot properly you need to switch the firmware to boot to UEFI mode!
C:\WINDOWS\system32#

一応20行目に "MBR2GPT: Conversion completed successfully" とあるので変換は成功したようですが、WinRE(Windows Recovery Environment: Windows)で ReAgent.xml を更新できないので手動で無効化/有効化してください、というメッセージが出ています。色々やってみたのですが、とりあえず回復の設定はあとからでも大丈夫そうです。

その下には「新しいシステムをブートする前にUEFIモードに切り替えないとだめよ」というメッセージもあります。うっかりここで再起動してしまうと大変なことになりそうです。

ということでここからはキャプチャはないのですが、再起動してUEFI画面(DELキー連打)を出して、CSM互換オプションを無効にしてPKを生成し、セキュアブートを有効化してもう一度再起動です。Windowsが起動する前に何度かUEFI画面で設定を確認し直す慎重さは必要かもしれません。

うれしいお知らせです。が表示されました。

WindowsにLua 5.1をインストールしてLuarocksする。

NeovimにはLuaJITが組み込まれています。これはLua 5.1がベースになったLuaJIT 2.1.0-beta3とのこと。ちなみにLua 5.1系自体は2012年2月17日にbug-fixリリースの5.1.5が最後です。その前年の12月に5.2.0がリリースされ、その後現在のバージョンは5.4.3になっています。

Pythonはちょろっといじってきたのですが、せっかくNeovimにLuaが組み込まれているのだし、VimScriptも難しいし、テキスト加工の自動化とかもLuaでできたら楽なのかな、と思ったのでLuaに手を出してみることにしました。

ということでちょっと調べてみると、Lua 5.1では文字列はbyte列として扱う、ということで、たとえばコマンドプロンプトでLuaインタプリタを起動し、string.len("あいうえお")とすると、
  • CP932環境では 10
  • CP65001環境では 5
です。一方Neovim(encoding=utf-8)で:lua print(string.len('あいうえお'))すると15が返ってきます。

ちょっとやってみただけなので間違ってたり環境依存だったり勘違いだったりするのかもしれませんが、まあそんな感じで一筋縄では行かなそうだし、本当に文字エンコーディングの問題は魂に刻み込まれた呪いのようです。

Windows 11が出るよ、と言われて、全部Unicodeになるの?と思ったらやっぱりならないみたいだし、この呪いはもはや「with 文字エンコーディング」として付き合っていかないとなのでしょうか。

閑話休題 それはさておき

調べてみると、Lua 5.1でも使えるutf8ライブラリがあるようです。starwindg/luautf8は、5.3のビルトインのものと互換性があるようで、これを使うのが一番良さそうです。ところがこれは LuaRocks を利用してインストールする形になっているので、Lua + LuaRocks が必要です。
 

Lua 5.1のインストール

ともかく、Luaをインストールしてしまいましょう。といっても、最新の5.4系ではなく、Neovimと同じ5.1系を選びます。具体的には最終版の5.1.5。

Lua DownloadページのToolsのところに、LuaBinariesというリンクがあるのでそこに飛びます。すると、[05/May/2014]のところに Lua 5.1.5 - Release 1 というリンクがあるのでそこをクリックします。
そこにある Tools Executables に実行形式が、Windows Libraries にDLLがあります。

使用しているNeovimは64bitビルドなので、ここでは lua-5.1.5_Win64_bin.zip を選びます。が!ここで注意なのですが、bin.zipのほうはVC+2005でコンパイルされています。そのためランタイムも必要になり、ちょっとめんどくさいです。

また、LuaRocks を動作させるためにはヘッダーファイルが必要となるため、上記 Windows Libraries から lua-5.1.5_Win64_dll16_lib.zip もダウンロードします。
bin.zipのほうはVC+2005でコンパイルされていますが、dll16_lib.zipはVS2019でコンパイルされています。

なので、余計なランタイムをなくすためにも、ここではソースもダウンロードして、Lua 5.1.5もVS2019でコンパイルし直します。ソースはtar ballになっていて、lua-5.1.5.tar.gz からダウンロードできます。

Lua 5.1のコンパイル

ダウンロードしたtar ballをほどいたら、VS2019のNative x64 コマンドプロンプトを開き、lua-5.1.5ディレクトリに移動します。INSTALLファイルを見るとプロジェクトを自分で作ってコンパイルしなさい、とありますが、ここでは簡単に etc\luavs.bat を起動します。必要に応じて src\luaconf.h を編集しなさいともありますが、特に希望はないのでそのままで。

コンパイルが無事に終われば、lua.exe、luac.exe、lua51.dll、lua51.libができています。ここではlua51.libを c:\Apps\Lua\lib に、その他を c:\Apps\Lua\bin にコピーします。
また、lua.h、lua.hpp、luaconf.h、lualib.h、luaxlib.hを c:\Apps\Lua\include にコピーします。lua.hppは etcディレクトリにあるのでご注意。
コピーしたら c:\Apps\Lua\bin にPATHを通して動作チェックです。

LuaRocksのインストール

次にLuaRocksをインストールします。といっても、Installation instructions for Windowsに従って実行形式ファイルをコピーするだけですが。
LuaRocksのダウンロードページから、Windows all-in-one executable (64-bit)をダウンロードします。このzipファイルを開くとluarocks.exeとluarocks-admin.exeがあるので、これを先程の  c:\Apps\Lua\bin コピーします。

コピーしたら、環境変数を設定します。
  • LUA_DIR : c:\Apps\Lua
  • LUA_BINDIR : c:\Apps\Lua\bin
  • LUA_INCDIR : c:\Apps\Lua\include
  • LUA_LIBDIR : c:\Apps\Lua\lib
あるいは、以下のようにしてconfigファイルを作成しておきます。
$ luarocks --lua-version 5.1 config --global variables.LUA_DIR c:\Apps\Lua
$ luarocks --lua-version 5.1 config --global variables.LUA_BINDIR c:\Apps\Lua\bin
$ luarocks --lua-version 5.1 config --global variables.LUA_INCDIR c:\Apps\Lua\include
$ luarocks --lua-version 5.1 config --global variables.LUA_LIBDIR c:\Apps\Lua\lib

します。Luaのデフォルトのバージョンは5.3になっているようで、5.1を利用する場合には --lua-version オプションが必要です。見落としているかもしれませんが、どうもデフォルトで5.1に固定するような設定はなさそうです。

luautf8のコンパイル

次はluautf8のコンパイルです。
これは、VS2019のx64 コマンドプロンプトを開いて、
$ luarocks --lua-version 5.1 --global install luautf8
とします。
$ luarocks --lua-version 5.1 --global install luautf8
Installing https://luarocks.org/luautf8-0.1.3-1.src.rock

luautf8 0.1.3-1 depends on lua >= 5.1 (5.1-1 provided by VM)
cl /nologo /MD /O2 -c -Folutf8lib.obj -Ic:\Apps\Lua\include lutf8lib.c
lutf8lib.c
link -dll -def:lua-utf8.def -out:lua-utf8.dll c:\Apps\Lua\lib/lua51.lib lutf8lib.obj
Microsoft (R) Incremental Linker Version 14.29.30133.0
Copyright (C) Microsoft Corporation.  All rights reserved.

   ライブラリ lua-utf8.lib とオブジェクト lua-utf8.exp を作成中
luautf8 0.1.3-1 is now installed in C:\Users\kats\AppData\Roaming/luarocks (license: MIT)
ちょっと深い場所に出力されていますが、ここでできた lua-utf8.dll をc:\Apps\Lua\bin にコピー、また Neovim から使うには c:\Apps\Neovim\bin にコピーすれば require で参照できます。

Lua 5.3の標準ライブラリと同様に使うために、lua-utf8 を utf8 として参照できるようにします。
> utf8 = require 'lua-utf8'
> print(utf8.reverse('あいうえお'))
おいうえあ
ただ、コマンドプロンプトとかCP932な環境なので今ひとつな感じ。Neovimだけならなんとかなるかしら。

Path.read_text()をリストに。

cp932からutf-8への文字コード変換。では、ファイルを明示的にオープンしなくてもテキストファイルをエンコード付きで読み込めることを書きました。

実はここで読み込めるテキストは、改行コード"\n"まで含めて1つの文字列になっています。ちょうど、改行付きのテキストファイルをrepr()したような感じです。

もしも1行ごとに取り出してなにかの処理をしたいとしたらこのままでは困りますから、リストにする必要があります。すごく簡単で当たり前の処理なのでわざわざ記事にするほどのものでもないのですが、str.split()を使います。
from pathlib import Path

textfile = Path("abc.txt")
content = textfile.read_text(encoding="utf-8")
c_list = str.split(content, "\n")
これでファイルの内容を読み出してリストにすることができました。

ちなみに、中間の読み出し結果が不要なら、
from pathlib import Path

textfile = Path("abc.txt")
content = str.split(textfile.read_text(encoding="utf-8"), "\n")
とすれば、最初からリストが得られます。ただし、改行コードがすべて置き換わっているので、必要に応じて行末に改行コードを付加しなくてはいけません。

cp932からutf-8への文字コード変換。

世の中、まだまだ文字コードの問題はなくなりません。特に日本語をはじめとするマルチバイト文字の文化圏では……。

ご多分に漏れずうちの環境でも同様で、Windows標準のFINDは率直に言って使いづらく、最近はripgrepthe Platinum Seacherなどを使っていますが。

それはともかく、プログラムからテキストファイルをいじりたいときに、文字コードが揃っていないととにかく大変です。個人的にはPCにあるすべてのテキストファイルはUTF-8であってほしいところですが、まだまだシフトJISがはびこっています。

なのでこれを一括でUTF-8に変換するにはどうすればいいかとちょっと前に検索したところ、Pythonのcodecs.StreamRecoder()を使ってストリームを流しながらcodecを通す、という方法があったのでこれを使っていました。

ところが最近pathlibをよく使うようになり、以前にos.walk()を使って取得していたディレクトリツリーのファイルリストをpathlib.Path.glob()に書き直しているときに、pathlib.Path.read_text()というのを見つけました。

Path.read_text()は以下のように使います。
from pathlib import Path

infile = Path("abc.txt")
content = infile.read_text(encoding="cp932")

outfile = Path("xyz.txt")
outfile.write_text(content, encoding="utf-8")
大きなサイズのファイルであれば読み込みサイズを加減する必要がありますが、小さいサイズならこれで十分です。明示的にファイルをopen()する必要すらありません。
あまり大きなファイルでは試していませんが、600KBのファイルを読み込んで処理するのは問題ないようです。

上記の例ではinfileoutfileを別にしていますが、Path.read_text()Path.write_text()は自動でファイルを開き、読み込み/書き込み処理をし、すみやかにファイルを閉じる、というところまでやってくれます。with open()...を使ったコンテキスト構文すら不要です。

また、ファイルは閉じられているので「読み込んですぐに文字コードを変えて書き戻す」ということもできます。
from pathlib import Path

textfile = Path("abc.txt")
content = textfile.read_text(encoding="cp932")
textfile.write_text(content, encoding="utf-8")
3行で文字コード変換できてしまいます。

おかげでコードがけっこう短くなりました。

SWDなら3線でいいとはいうものの。

 安価で優秀なデバッグプローブはないかしら、と探したら、 Raspberry Pi Debug Probe というのがあったんですが、これは3線がにゅるんと出てるだけです。 もちろんSWDなら3線を繋げばいいのではありますが、汎用的に考えるなら5x2のリボンケーブルコネクタが欲し...