軽量 HTML ブラウザ Cobalt と YouTube on TV

# 本記事の概要

- 軽量な HTML アプリケーションプラットフォーム Cobalt の紹介

![657896f43b72a5d2a2280268.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502849/1e5ae9cf-cdff-04a8-40bf-343f474c25f5.png)

# Cobalt

## Cobalt とは

YouTube on TV を実行するための軽量HTMLブラウザ。TV やゲームコンソール、カーナビ等の組み込み機器で動かすことを想定しています。

https://cobalt.dev/

> A high-performance, small-footprint platform that implements a subset of HTML5/CSS/JS to run applications, including the YouTube TV app.

## YouTube on TV とは？

YouTube コンテンツを閲覧するためのウェブアプリケーション。**YouTube TV (https://tv.youtube.com/) とは別物です。**
「on TV」の通り、TVのような環境でも快適に閲覧できるよう工夫されています。例えば、

- 方向キーといくつかのボタンしかないようなリモコンでも快適に操作できるようなユーザーインターフェイス
- 文字入力のための仮想キーボードがウェブアプリケーション上で実装済み
  - プラットフォームで文字入力機能を実装しなくても良い
  - 多言語対応。<small>ただし、ひらがなは入力できるものの漢字変換が出来ない等、CJK のサポートの評判は良くない。</small>
- 動画を複数同時再生しない
  - 動画を複数同時にデコード出来ないハードウェアでも再生できるようにするため

YouTube on TV はウェブアプリケーションなので、URL から簡単にアクセスできます。

https://www.youtube.com/tv

通常、PC 等からアクセスすると、PC 版の `youtube.com` に転送されます。

アクセス元が PC かどうかの判定には User-Agent が使われています。そのため、例えば User-Agent を Cobalt のものに置き換えることで PC 用ブラウザでも閲覧できるようになります。
以下は、Chromium でコマンドライン引数 `--user-agent` を指定して起動する例です。

```
chromium https://www.youtube.com/tv --incognito \
  --user-agent='Mozilla/5.0 (X11; Linux x86_64) Cobalt/24.lts.13.1032728-gold (unlike Gecko) v8/8.8.278.8-jit gles Starboard/14, SystemIntegratorName_DESKTOP_ChipsetModelNumber_2023/FirmwareVersion (BrandName, ModelName)'
```

## Cobalt はブラウザだから任意の Web サイトが見れる？

ブラウザの Cobalt に話を戻します。
Cobalt はすべての HTML 仕様を実装しません。サポート範囲は以下のサイトに記載されています。

https://cobalt.dev/development/reference/supported-features.html 

例えば、対応しているタグは下記のみでとても少ないです。

`<a>`, `<audio>`, `<body>`, `<br>`, `<div>`, `<head>`, `<html>`, `<link> (with type="text/css")`, `<lottie-player>`, `<meta>`, `<script>`, `<span>`, `<style>`, `<title>`, `<video>`

そのため、ほとんどの Web ページは、開こうとすると表示が崩れます。
また、Shift_JIS に対応していないので、よく話題になる http://abehiroshi.la.coocan.jp/top.htm はそもそも表示できません。
ほぼ YouTube on TV 専用ブラウザ。

## Cobalt の移植層 (Starboard layer) について

Cobalt をハードウェアや OS の違いから完全に分離するために、Cobalt は OS の API やライブラリを直接呼び出さず、変わりに OS の抽象化である Starboard の API を使います（でも C++STL は使える）。

Starboard から提供されている API は、ウィンドウ管理やファイルアクセス、マルチメディア系、EGL/GLES、状態変数やスレッドのような POSIX 系などさまざま。

Starboard API について、いくつかサンプル `starboard/examples` が用意されているため、Starboard を利用した Cobalt 以外のアプリケーションも作れそうです。

## Evergreen について

移植層として Starboard を説明しましたが、Starboard は Cobalt と分離して別々のオブジェクトとしてビルドすることもできます。
これにより、Cobalt だけをネットワーク経由で自動ダウンロード・更新できるようになります。このような自動アップデートシステムを Evergreen と名付けているようです。

Evergreen によって Starboard から分離された Cobalt アプリケーションは、プラットフォームに依存しないので、Starboard API バージョンと CPU アーキテクチャ（x64 や aarch64）さえ一致していれば、 Cobalt 1 つのバイナリで様々なプラットフォームに配布・更新できます。

# x64Linux 向けビルド

Docker Compose の設定ファイルが提供されているので、ビルドもお手頃にできます。

## 環境

- Ubuntu 22.04 x64
- Docker version 24.0.7 (Docker Compose V2)
  - `docker compose` コマンド(ハイフンなし)を使用するバージョンです
- Cobalt `24.lts.13` https://github.com/youtube/cobalt/tree/24.lts.13

ビルド方法は https://cobalt.dev/development/setup-docker.html や https://github.com/youtube/cobalt/blob/24.lts.13/cobalt/site/docs/development/setup-docker.md に案内があります。

## ソースコード取得

リポジトリは 2 つ。

- https://cobalt.googlesource.com/cobalt 
- https://github.com/youtube/cobalt 

main ブランチの状況を見ると、開発は GitHub で行われているようです。今回は諸般の事情により開発途上の main ブランチ上にあるコミットも取り込みたいため、GitHub を remote として指定し、選んだバージョンをチェックアウトします。

```
$ git clone https://github.com/youtube/cobalt && cd cobalt
$ git checkout refs/tags/24.lts.13
$ git checkout -b private_24.lts.13
```

## ビルド

公式サイトを読むと、

> The simplest usage is:
> 
> `docker compose run <platform>`

実際にやってみると、`docker compose` がエラー吐きます。

```
$ docker compose run linux-x64x11
parsing /tmp/work/cobalt/docker-compose.yml: yaml: unmarshal errors:
  line 33: mapping key "<<" already defined at line 32
  line 33: mapping key "<<" already defined at line 32
  line 33: mapping key "<<" already defined at line 32
  line 33: mapping key "<<" already defined at line 32
```

GitHub の Issue を探すと、 Docker Compose V2 に関する修正の PullRequest が見つかります。
つまり、エラーになっていたのは手元の Docker Compose が新しすぎるため。

https://github.com/youtube/cobalt/pull/1335

上記の PullRequest に該当するコミット
https://github.com/youtube/cobalt/commit/791924e20f7ba61ec16b70f75c7c91ec62d2b283

このコミットは、 `24.lts.13` には取り込まれていないため、cherry-pick します。

```
$ git cherry-pick 791924e20f7ba61ec16b70f75c7c91ec62d2b283
Auto-merging CONTRIBUTING.md
Auto-merging docker-compose.yml
CONFLICT (content): Merge conflict in docker-compose.yml
Auto-merging docker/linux/base/build/Dockerfile
error: could not apply 791924e20f7... Docker Compose V2 and related build fixes (#1335)
```

2行 Conflict が発生しますが、vscode 等で Conflict を解決しておきます。
これでビルドが開始できるようになります。

```
$ docker compose run linux-x64x11
```

デフォルトでは debug 版がビルドされます。製品版をビルドする場合は、環境変数から指定します。

```
$ docker compose run -e CONFIG=gold linux-x64x11
```

出力ディレクトリを確認して、 cobalt が出来ているかどうか確認します。

```
$ ls out/linux-x64x11_debug/cobalt
out/linux-x64x11_debug/cobalt
```

## 起動

cobalt を実行するだけです。

```
$ cd out/linux-x64x11_debug/
$ ./cobalt
```

デバッグ版であれば devtools が使えます。`--remote_debugging_port=8080` をコマンドラインに追加すると、 devtools の http サーバが起動します。機能は簡略化されていますが、DOM を確認できます。

```
$ ./cobalt --remote_debugging_port=8080
```

![6579f64c3b72a5d2a228155c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502849/71ce5f8e-8245-94bb-c646-bba19da3e88c.png)


## その他のビルド

x64 向けのビルドのみでしたが、Android や Raspberry Pi 向け（OSイメージ指定あり）も用意されています。

# まとめ

- 軽量ブラウザ Cobalt と YouTube on TV の紹介
- さまざまな環境で実行するために Starboard API や Evergreen の仕組みがある
- Linux x64 向けの Cobalt をビルドして動かしてみる。