中華の怪しいTWSイヤホン i7S

i7s TWS

中華の通販サイトでよく見かける怪しいTWS(True Wireless Stereo)なイヤホン。Bluetooth 5.0対応、バッテリー駆動での音楽鑑賞(非通話)が1.5〜3時間程度というのが多いようだが、これがとても安い。TWSは左右で2個のイヤホンがセットである必要はないので片側イヤホン+直充電ケーブル、左右イヤホン+直充電ケーブル、左右イヤホン+充電ポッドなど、2〜4種類で販売されるようだが、イヤホン片側だけなら150円なんてのもある。
TWSでしかも糞安いやつは以前から気になってはいたものの「どうせ音が悪いんでしょう?」ってことで買わずにいた。が、突然気が変わってポチってしまった。

今回購入したのは上の画像のやつi7S TWSというやつ。「左右イヤホン+充電ポッド」タイプでAliExpressでのお値段388円で送料無料(価格は変動します)。

i7s TWS 1
送料無料なので中国側の配送便がCainiao Super Economy(菜烏)。注文が10月下旬だったので配達まで20日程度かかった。飛行機に乗るところで10日ほどの滞留で、Cainiaoにしては普通。
ビニールの封筒で中に箱は入ってなくて商品をプチプチ越しに触れるような梱包。

i7s TWS 2
封筒の中身。ジップ袋の超簡易梱包。なんか汚い感じ。

i7s TWS 3
袋の中味。
ラップに包まれた充電ポッド。イヤホンは充電ポッドの中にある。中国語と英語のマニュアル。USB-AとmicroUSBの充電用ケーブル。ACアダプタは付属しない。

i7s TWS 4
AA電池(単3電池)4本との大きさ比較。小さいといえば小さいけど、耳の穴に挿す部分がAA電池の太さくらいあるって耳の小さい人は大丈夫なのかしら。

i7s TWS 5
イヤホンを充電ポッドから引き抜くと自動的にイヤホンの電源が入るということだが、技適のないBluetoothの機器を迂闊に使ってしまうと電波法違反になる。
技適未取得機器を用いた実験等の特例制度で実験を目的とする届け出を行う。以前の中華ルーターのときにも書いたが、本人確認登録(マイナンバーカードでオンライン登録が早い)さえ済ませていれば届け出は簡単で、今回のイヤホンなら5分ほどでオンライン登録できる。届け出が終われば許可が下りるのを待つとかはなくてすぐに使用可能。

i7s TWS 6
イヤホンの片側を充電ポッドから引き抜くとイヤホンは音源の機器とペアリングを行おうとして赤と青のランプが交互に光る。
が、ペアリングなんかしないで重量を量った。イヤホン片側は約4g。イヤホンには65mAhのバッテリーが内蔵されているが、この軽さ。その分、音楽の連続再生可能な時間は短めで1.5-2時間(商品紹介ページの情報)。

i7s TWS 7
充電ポッドも量ってみた。画像のとおり約33gとこれも軽いが、これで左右のイヤホンが入った状態。イヤホン片側が4gなので左右で8g。これを引くと充電ポッドのみの重量は約25gということになる。充電ポッドは単独でイヤホンに充電するための950mAhのバッテリーが入っているということになっているがこんなに軽くて本当かしら。中華製品なので数字は大きく割り引いた方が良いかもしれない。

i7s TWS 8
充電ポッドの底にはイヤホンに充電するための接点が付いていて、イヤホンの筒の端の穴に挿さるようになっている。

i7s TWS 9
先にイヤホンが充電ポッドに入った状態で、充電ポッドをmicroUSBケーブルとつないで2時間ほど充電する。
音源側機器のBluetoothのスイッチをオフにする。
充電ポッドから左右両方のイヤホンを引き抜く。
左右のイヤホンのペアリングが行われる。(普通は自動で行われる筈)
片側のイヤホンの筒の部分が赤・青に光っている間にスマートフォンやコンポ、テレビ、トランスミッターなどのBluetoothの音源側機器のBluetoothのスイッチをオンにして「ペアリングを開始」をしてやると音源側とイヤホンのペアリングが行われる。

ペアリングに失敗すると左右両側のイヤホンが鳴らない。または片側だけ鳴らないということになる。左右のイヤホンのサイドにあるボタンを同時に長押しすると強制的にペアリングモードに入るのでペアリングをやり直す。ペアリングは基本的には1度成功したら繰り返す必要はない。なお、イヤホンは通信相手がいないと赤・青のランプが光るみたい。

i7s TWS 10
スマートフォン(Android)とi7Sを接続しみた。オーディオコーデックはSBCであると表示されている。i7SはSBCのみの対応なのでAACやaptXなどに切り替わることはない。

なにしろ400円以下のTWSイヤホンなので、昔の100均の有線イヤホンにも劣るペラペラスカスカな酷い音を予想していて、そういう風にブログにボロカスに書いてやろうと思っていたが、意外と普通な音。変なクセもないので聴きやすいくらい。これは意外だった。
イヤホン本体が軽いので耳の装着感も悪くない。装着していてポロっと取れそうな見た目に反して納まりも良い感じ。(耳の穴の大きさによるかも)
ただし、省電力で動いているからか、電波はかなり弱いっぽい。TWSは線もネックバンドもないので寝るときに使うのに良いかなと思って買ったのだが、寝た状態で頭の向きを変えただけで音が途切れたりイヤホンを装着した状態で耳の近くに手をかざす(耳を塞がない)程度でもやはり音が途切れる。音が途切れるだけでなく、接続OFFになることも。だからイヤホンを装着した状態で油断ができない。
あと、やっぱり再生時間が1.5時間は短すぎるかも。新品でこれだと暫く使ってバッテリーが劣化するとさらに短くなる。まぁ糞安いので新しいのを買えば良いんだろうけど。

TWSは左右のユニットがそれぞれバッテリーを搭載している。で、少なくとも購入したi7Sの個体は片側(左耳側)のバッテリーが右側用に比べてかなり持ちが悪い。だから、いつも左耳用だけ早々にバッテリー警告(英語音声)が出て、その後数分で片側(左耳側)だけ電源断。右耳側はその後30分ほど使えるけど。

と、いうことで、i7Sは意外にも音は悪くはなかったけど、「技適未取得機器を用いた実験等の特例制度」の1度の届出で有効な180日を待たずに廃止届出をすることになるかな?

youtube-dlの使い方備忘録

動画編集
©いらすとや.

YouTubeなど幾つかの動画サイトから動画をダウンロードできるyoutube-dlが、RIAA(全米レコード協会)から削除要請が出されてGitHubからリポジトリが削除されたのが10月下旬。RIAAの主張が強引だったこともあってか反論が相次ぎ、削除要請が不当と判断されてリポジトリが復活した模様。ただ、11月上旬時点で既に幾つかyoutube-dl関連のリポジトリが出来ていて、それが削除されていなかったし、pipでインストール・更新することも可能だったので、youtube-dl関連全てが一斉に削除かつ関連リポジトリ作成も禁止のような扱いではなかったみたい。

「がとらぼ」の中の人はYouTubeにはゴミ以下の動画をまれに上げる程度だけど、作った動画(アップロード前のファイル)を保存せずに捨てることが多いので、アップロードした動画を取り戻す意味でyoutube-dlを使うことがある。もちろん、YouTubeからダウンロードした動画はアップロード前の動画より遥かに劣化したものなのでクオリティーを求める人は作成した動画を捨てたりせずにバックアップしておいて欲しい。

で、youtube-dlはそんな使い方なので1年に1度触る触らないか程度。当然使い方をすぐに忘れてしまう。
そこで、自分向けの備忘録。

youtube-dlのインストール・更新

youtube-dlはバージョンが古いと使えないことが多い。
なのでLinuxのパッケージなどに頼るとおよそロクなことにならない。
つまりソフトウエア管理ツール・パッケージでインストールするとハズレる。手動でインストール・更新するようにしたい。

使用頻度が低いと使用しようとする度に更新しないといけないかも。

http://rg3.github.io/youtube-dl/download.html
https://youtube-dl.org/ で最新版のバージョンを確認。(確認だけ)

Linuxでpipの存在(インストールされているか)を確認
$ which pip
または
$ which pip3
pipがインストールされていないならインストールする。(下の実行例はDebian/Ubuntu系)
$ sudo apt install python-pip
または
$ sudo apt install python3-pip
youtube-dlのインストールまたは更新
$ sudo pip install --upgrade youtube_dl
または
$ sudo pip3 install --upgrade youtube_dl

インストール・更新とも同じで、これだけ。(--upgradeの代わりに-Uでも可)

更新の例 (ちょっと古いメモだけど)
$ sudo pip install -U youtube-dl
Collecting youtube-dl
  Downloading https://files.pythonhosted.org/packages/41/4f/b9d6a4dff6cf176d593d494deade44db19654adc3188b7e2842f21a1f31b/youtube_dl-2019.4.24-py2.py3-none-any.whl (1.8MB)
    100% |████████████████████████████████| 1.8MB 344kB/s 
Installing collected packages: youtube-dl
  Found existing installation: youtube-dl 2019.2.18
    Uninstalling youtube-dl-2019.2.18:
      Not removing or modifying (outside of prefix):
      /usr/bin/youtube-dl
      Successfully uninstalled youtube-dl-2019.2.18
Successfully installed youtube-dl-2019.4.24

あと、いろいろするならffprobeとffmpegが必要になるようなのでシステムに入っていないならインストール。
おそらくffmpegをインストールすると両方解決する筈。

$ sudo apt install ffmpeg

youtube-dlの使い方

基本形
$ youtube-dl 動画URL
または
$ youtube-dl 動画ID
または
$ youtube-dl プレイリストID   (プレイリストIDの前に -i を追加するとエラーを無視するのでオススメ)

YouTubeだと https://www.youtube.com/watch?v=00000000000 のようなのが動画URL、そのv=の後の00000000000が動画ID。
https://www.youtube.com/watch?v=00000000000&list=AAAAAAAAAAAAA のlist=の後のAAAAAAAAAAAAAがプレイリストID。

とても簡単だが、ダウンロードしたファイルの動画フォーマットの種類や解像度や音声形式が期待していたものとは違うかもしれない。

YouTubeだと1つの動画と思っているものが、実は複数の形式で保管されている。また、動画ファイルの種類が複数あるだけでなく、動画ファイルに含まれる動画・音声のフォーマットも複数ある。フォーマットを指定すれば期待通りの動画・音声を取得できる。

対象動画のビデオと音声のリストを表示する
$ youtube-dl --list-formats 動画IDまたは動画URL
実行例
$ youtube-dl --list-formats 00000000000
[youtube] 00000000000: Downloading webpage
[youtube] 00000000000: Downloading video info webpage
[youtube] 00000000000: Downloading js player vflq4d8Te
[info] Available formats for 00000000000:
format code  extension  resolution note
171          webm       audio only DASH audio  126k , 1fps, vorbis@128k, 10.41MiB
140          m4a        audio only DASH audio  128k , m4a_dash container, mp4a.40.2@128k, 12.22MiB
278          webm       256x144    144p   97k , webm container, vp9, 24fps, video only, 5.85MiB
160          mp4        256x144    144p  119k , avc1.42c00c, 12fps, video only, 10.48MiB
242          webm       426x240    240p  160k , vp9, 24fps, video only, 6.30MiB
134          mp4        640x360    360p  248k , avc1.4d401e, 24fps, video only, 14.27MiB
133          mp4        426x240    240p  250k , avc1.4d4015, 24fps, video only, 23.46MiB
243          webm       640x360    360p  285k , vp9, 24fps, video only, 11.08MiB
244          webm       854x480    480p  438k , vp9, 24fps, video only, 16.46MiB
135          mp4        854x480    480p  525k , avc1.4d401e, 24fps, video only, 29.26MiB
247          webm       1280x720   720p  814k , vp9, 24fps, video only, 30.29MiB
136          mp4        1280x720   720p 1077k , avc1.4d401f, 24fps, video only, 60.78MiB
248          webm       1920x1080  1080p 1323k , vp9, 24fps, video only, 52.05MiB
137          mp4        1920x1080  1080p 2034k , avc1.640028, 24fps, video only, 130.45MiB
17           3gp        176x144    small   81k , mp4v.20.3, mp4a.40.2@ 24k (22050Hz), 7.84MiB
36           3gp        320x180    small  225k , mp4v.20.3, mp4a.40.2 (22050Hz), 21.73MiB
18           mp4        640x360    medium  343k , avc1.42001E, mp4a.40.2@ 96k (44100Hz), 32.99MiB (best)

行頭の数字がフォーマットコードなので、上の例ではmp4の動画の1920x1080の解像度は137、音声のm4aは140ということが判る。
ダウンロードしたい動画によって存在するフォーマットが違うことがあるので、例えばどの動画でもフォーマットコード137のmp4動画1920x1080があるとは限らない。

フォーマットを指定してダウンロード

上で動画に含まれるフォーマットの種類を調べたら、取得するフォーマットを決める。
たとえばm4a(140)の音声が欲しいとする。

$ youtube-dl -f 140 動画IDまたは動画URL

動画と音声のフォーマットをそれぞれ希望の種類でダウンロード後にマージしたいことはよくある。
動画に含まれる動画(映像)と音声のフォーマットの種類を調べたら、欲しい組み合わせでを決める。
たとえば、上のmp4動画1920x1080 (137)とma4音声でダウンロードしたいとする。出力はmp4形式とする。

$ youtube-dl -f 137+140 --merge-output-format mp4  動画IDまたは動画URL
存在しないフォーマットは指定不可

ダウンロードしてFLACに変換

音声だけライブラリ化したいということがある。編集にかけるだけならダウンロードしたファイルを変換せずにそのまま利用する方が良いとは思うが、好みの形式の音声ファイルにしてしまいたいことってある筈。今回はFLACにする例。

$ youtube-dl -x --audio-format flac 動画IDまたは動画URL

FLACを生成するだけでなく、ダウンロードした動画を残すなら -k を付ける

$ youtube-dl -k -x --audio-format flac  動画IDまたは動画URL

FLACは非可逆圧縮なので音声が劣化しないとはいえ、YouTubeにアップロードしたことでアップロード前の音声よりは劣化してしまっていると思われる。ただし、その劣化した音声をさらにmp3などに再変換するよりははるかにマシ。

Caddy ウェブサーバー

Caddy
©いらすとや.

メモリ容量が512MBしかないSBCでウェブの提供を行おうとしたが、このホストはicecast2を動かしていて、既にメモリの80%以上を消費しているので、さらにPHPだとかPythonだとかを使ったCMSを動かすとかは無理そう。そこで別ホストのウェブサーバのコンテンツを表示させるリバースプロクシを建てることにした。 そのリバースプロクシにはいつも使っているNginxではなく軽量で簡単なCaddyを使うことにした。噂によるとHTTP/2には自動対応、つまりSSL/TLSの設定は自動。さらにHTTP/3のQUICも使えるとか。凄いね。
Caddyは初めて使うのでググったのだが、新旧情報が入り混じってて簡単な筈なのに意外と苦労することになった。

Caddy serverをインストール

Caddyを非商用で使う場合は https://caddyserver.com/download からバイナリファイルをダウンロード。ウェブ画面上部のPlatformの欄でCaddyを使用するホストのOSの種類とCPUの種類の合うものを選択して、右端の[Download]で取得できる。

ダウンロードしたファイル(今回はcaddy_linux_arm64)を/usr/bin/あたりに置く。ファイル名はcaddyにでもしておく。実行権限はダウンロードしたファイルに付いている筈だけど確認して無ければ付けておく。
インストールはこれだけ。

Caddyを触ってみる

$ caddy help
Caddy is an extensible server platform.

usage:
  caddy <command> [<args...>]

commands:
  adapt           Adapts a configuration to Caddy's native JSON
  build-info      Prints information about this build
  environ         Prints the environment
  file-server     Spins up a production-ready file server
  fmt             Formats a Caddyfile
  hash-password   Hashes a password and writes base64
  help            Shows help for a Caddy subcommand
  list-modules    Lists the installed Caddy modules
  reload          Changes the config of the running Caddy instance
  reverse-proxy   A quick and production-ready reverse proxy
  run             Starts the Caddy process and blocks indefinitely
  start           Starts the Caddy process in the background and then returns
  stop            Gracefully stops a started Caddy process
  trust           Installs a CA certificate into local trust stores
  untrust         Untrusts a locally-trusted CA certificate
  validate        Tests whether a configuration file is valid
  version         Prints the version

Use 'caddy help <command>' for more information about a command.

Full documentation is available at:
https://caddyserver.com/docs/command-line

こんなコマンドが使えるみたい。

$ caddy version
v2.2.1 h1:Q62GWHMtztnvyRU+KPOpw6fNfeCD3SkwH7SfT1Tgt2c=

とりあえず、バージョンを確認しておく。Ver.1系とVer.2系で設定の書き方が全然違うみたいなので。今後はver.2系の情報だけ探すべき。
一応、公式のドキュメントは https://caddyserver.com/docs/ にあるのだが、個人的には読んでもピンとこなくて各項目で何が指定できるのかなんか良く解らなかった。
設定のサンプルをググるとVer.1系の情報が多くヒットして役に立たないだけでなく混乱するので困る。

Caddyをリバースプロキシにする

今回はCaddyをリバースプロクシにするのだが、先ずは設定ファイルを作らずにコマンドラインから1行で実行してみた。

$ caddy reverse-proxy --from caddy.example.com --to 192.168.0.1:443
または
$ caddy reverse-proxy --from caddy.example.com --to https://another.example.com

caddy.example.comが、Caddyの動いているホストのFQDNとする。
192.168.0.1:443やhttps://another.example.comはコンテンツのある外部ウェブサーバ。ここのIPアドレスやURLの書き方を混ぜると挙動が怪しいようなので注意。特に接続先のホスト(another.example.com側)が名前ベースのバーチャルホストの場合にデフォルトサーバが表示されたりデフォルトサーバが指定されていない場合にFQDN順で最初にヒットするバーチャルホストのコンテンツが表示されたりすることになる。
なお、コンテンツ側のホストは基本的にHTTPSであること。HTTPのウェブサーバを指定するとおそらくNGになるかな?
上の簡単なコマンド1つで自動的に Let's EncryptからTLS証明書を取得してHTTPSサーバとして起動してくれる。なんて簡単なの。

自動で取得した証明書関係のファイルは ~/.local/share/caddy/certificates下に保存される。 ~ は実行ユーザーのホームディレクトリ。

curlでリバースプロキシに接続してレスポンスヘッダ(+コンテンツ本体)を調べてみる。
curl -i https://caddy.example.com
HTTP/2 200 
accept-ranges: bytes
content-type: text/html
date: Mon, 16 Nov 2020 04:37:05 GMT
etag: "5fb11437-5b"
last-modified: Sun, 15 Nov 2020 11:42:47 GMT
server: Caddy
server: nginx
content-length: 20

another.example.com (コンテンツ)

簡単に動くのは素晴らしいのだけど、レスポンスヘッダにserver行が2つ(Caddyとnginx)あって気に入らない。ちなみにここで表示されているnginxはanother.example.comのウェブサーバが出したものを表示してるよう。とりあえずCaddy側を隠したいが、どうせ隠せるのであればserver行の存在自体が全部要らない。
そこで、設定ファイルでヘッダを操作する。

/etc/Caddyfile (新規作成)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
caddy.example.com {
    reverse_proxy {
        to https://another.example.com
    }
    header / {
        -Server
        Strict-Transport-Security "max-age=31536000; includeSubDomains"
    }

}

接続先のIPアドレス:ポートまたはURLの前の to は必要。
ついでにヘッダを追加する例としてHSTSを1行入れている。必須じゃないので気に入らないなら7行目を削除。

作成した/etc/Caddyfileを指定してcaddyを実行する。
$ caddy start --config /etc/Caddyfile
startはバックグラウンドで実行。caddy stop で停止。フォアグランドで動かすならstartの代わりにrunを使う。
curl -i https://caddy.example.com
HTTP/2 200 
accept-ranges: bytes
content-type: text/html
date: Mon, 16 Nov 2020 05:02:36 GMT
etag: "5fb11437-5b"
last-modified: Sun, 15 Nov 2020 11:42:47 GMT
strict-transport-security: max-age=31536000; includeSubDomains
content-length: 20

another.example.com (コンテンツ)

server行が消えて、追加したstrict-transport-security行がある。
一応満足。

メモリの使用量はNanoPi NEO2のArmbian(Debian Focal Fossa)で8MB程度(常駐のみ)、+α (処理時)。まぁ一応軽い。
今後、簡単にウェブサーバを建てたいと思ったら選択肢の1つ入れるかな。ただし、ドキュメントが何かイマイチ解らないのが問題かも。