OGK KAMUI-3 (L) は MajestyS のメットインに収まらない
OGK KAMUI-3 Lサイズ(頭囲59-60cm) はマジェスティS(2014)のメットインに収まんないです(たぶん現行モデルでも同じかと)。
メットインのくぼみにメットの顎部をあわせれば後頭部のフィンがメットイン後部に干渉して収まりきらず、後頭部を収めれば顎の部分がくぼみに収まらずでどちらにしろ収まらないorz
シートを無理矢理押し込めばロックはかかるものの、かなり無理がかかる感じなので数分程度ならともかく常用しないほうがよさげ。
どこかに各社メットイン-メット適合情報みたいなのまとまってりゃいいんだけどねぇ……
- マジェスティS メットイン ジェットヘルメット/フルフェイスヘルメット 適合情報 | FUTUREWING.net
- 価格.com - 『2018モデルの収納可能ヘルメット』 ヤマハ マジェスティS のクチコミ掲示板
- mixiヘルメット - マジェスティS/SMAX | mixiコミュニティ
x264 UTF-8になったとかそんなところのメモ
H265 のご時世なのに、端末やら何やらの都合で x264 にしがみついてるわけですが、昨秋に入ったコミット 7ab4c928 で、 x264 がいろいろエラーを出すようになったのでメモ。
commit 7ab4c928ef4511ea5753a36a57c3506d9fd5086b
Author: Henrik Gramner <henrik@gramner.com>
Date: Sat Sep 12 19:24:00 2020 +0200
Add support for long filenames on Windows 10何があったかというと、manifest ファイルが追加されてその中で activeCodePage UTF-8 という指定が付いたので、x264 プロセスのデフォルト文字コードが UTF-8 になったというそういうことです。
正道の対応策は「x264 が読むファイルは全てUTF-8にする」です。
直前のコミット d198931a63 でも「GPAC が UTF-8 サポートしてるから~」とかあるので UTF-8 統一が方針に則った方向と思います。
この変更で出るようになったエラーがこんなのです↓ (現行の master fa264466 のビルドで SJIS なファイルを読んだ場合のエラー)
中身にSJIS(非ASCII)を含む avs ファイルを入力にした場合。例えば日本語パスから Import した場合のエラーメッセージ。
avs [error]: Import: couldn't open "文字化け化け" (Enc.avs, line 11) x264 [error]: could not open input file `Enc.avs'
avs の中で (DGIndex で Demux した) d2v を読んでいて、d2v の中に日本語パスがあった場合のエラーメッセージ。
avs [error]: Avisynth open failure:MPEG2Source: Could not open one of the input files. (Enc.trim.avs, line 4) (Enc.avs, line 13) x264 [error]: could not open input file `Enc.avs'
対策としては以下のどれかで、上から順におすすめです(上で書いたとおりUTF-8化路線なので)。
- x264 が読むファイルは全て UTF-8 にする。
- バッチの途中とかでファイルの文字コード変換かけるようにする。など。
- x264 が読むファイルをASCIIに統一する。
- 上の亜種。日本語パスなど使わず全てASCIIで通せば自動的に UTF-8 対応に。
- 7ab4c928 を含まないビルドを作る。
エンコードチェーン見直さないと。。
いまさら Office2019 のインストールに戸惑ったのでメモ
Amazon で購入した Office Home and Business 2019 を2台目にインストールしようとして、出てきたメッセージなどに戸惑ったのでメモ。
Amazon なので、「アカウント&リスト」→「ゲーム&PCソフトダウンロードライブラリ」とたどると、結局「Office.comへ」と setup.office.com に飛ばされます。
そこで MS アカウントでログインするわけですが、その後に出てくるのがいかにもエラー然とした「このプロダクトキーはすでに使用されています。」というメッセージがなので、ここでドパっといやな汗が出るわけです。

まぁMSだし。と気を取り直し、そこに出ている「Microsoft アカウントからインストールする」リンクをたどると今度は「サブスクリプションが見つかりません。別アカウントを使用して購入した場合。 foobar@example.com でサインインしています。」と、またいかにも機械翻訳なメッセージを吐き出してくれるのでいやな汗の粘度も増すわけです。

ここで出ているメッセージやら「Office 2019 インストール」やらでググったりしてしまうわけですが、ここでの正解は「サブスクリプションに戻る」をクリックすることで、そうすると「サービスとサブスクリプション」のページに移動して購入した Office 2019 が表示され、そこの「インストールする」からネットワークインストーラがダウンロードできるという流れです。
とりあえず最初からこのページを出してくれと問い詰めたい。。

ちなみにこのインストーラ、(ちょっと知ってるパソコン先生にとっては)性格が悪く、問答無用でフルインストールするので「64bit版入れろ。WordとExcelとパワポだけでいい。いらんもの入れるな。」とかいう場合はカスタムインストールを設定する XML ファイルを書いてインストーラの起動時オプション configure に渡してやらないといけません。
<Configuration>
<Add OfficeClientEdition="64">
<Product ID="HomeBusiness2019Retail">
<Language ID="ja-jp"/>
<ExcludeApp ID="Access"/>
<ExcludeApp ID="Groove"/> <!-- Onedrive for Business -->
<ExcludeApp ID="Lync"/> <!-- Skype for Business -->
<ExcludeApp ID="OneDrive"/>
<ExcludeApp ID="OneNote"/>
<ExcludeApp ID="Outlook"/>
<ExcludeApp ID="Publisher"/>
</Product>
</Add>
</Configuration>
OfficeSetup.exe /configure custom.xml
昨今は1TB程度のストレージが当たり前になってるので、「とりあえず全部入れときゃ文句でないだろ」な富豪的プログラミングならぬ富豪的インストールなものが多くなりましたねと小並感。
Office のカスタムインストールについては以下サイトを参考にしました。
フロント向け webpack で "regeneratorRuntime is not defined" エラーが出たときの対処
まとめ
@babel/preset-env の targets 設定を見直して、Babel のターゲット指定を適切にしてやると無駄なPolyfillも使わずエラーもなくなる。
内容
webpack@4.43.0, babel-loader@8.1.0 な環境。対象はフロント(ブラウザ)用。
エラーメッセージで検索すると先例が色々とあるので、対処そのものは難しくないと思います。
async/await を bable でトランスパイルしたはいいが、必要な regeneratorRuntime が無いのというのがエラー要因なので、
- 必要な polyfill を追加する
- トランスパイル先のターゲットを要件に合わせて設定する
- @babel/runtime を入れる
あたりが対処方法になるかと思います。
自分の場合はモダンブラウザがターゲットで IE11 は対象外なので、polyfill は放り投げてトランスパイル先をちゃんと指定してやる方向で webpack.config.js の babel-loader の設定に targets を次のように指定してやりました。
loader: 'babel-loader',
options: {
presets: [ ['@babel/preset-env',
{
"targets": {
"browsers": "since 2019"
}
} ] ]
}
@babel/preset-env · Babel targets.browsers
@babel/preset-env のデフォルトだと次の通りの指定になっているので IE11 もターゲットに含まれているのですが、
> 0.5%, last 2 versions, Firefox ESR, not dead
since 2019 をターゲットにしてやると文字通り 2019 年以降リリースのブラウザのみがターゲットになるので async/await はトランスパイルされず、そのまま使われるのでエラーも無くなり無用なpolyfillもいらずで丸く収まります。
node.js にしろブラウザにしろ、最近のものは async/await には対応しているので、Babel 使うときはターゲットをちゃんと指定しましょうというオチでした。
x264 + L-SMASH を Windows 上でビルドする
MP4 muxer に L-SMASH を使った x264 のビルド手順。
基本は以下の過去トピの通り MSYS2 上で進め、 「GPAC のビルド」の部分を L-SMASH に置き換えるだけ。
L-SMASH のビルド
L-SMASH を公式GitHubリポジトリ GitHub L-SMASH's official repo から clone します。
$ git clone https://github.com/l-smash/l-smash.git Cloning into 'l-smash'... remote: Enumerating objects: 5, done. remote: Counting objects: 100% (5/5), done. remote: Compressing objects: 100% (5/5), done. remote: Total 7412 (delta 0), reused 1 (delta 0), pack-reused 7407 Receiving objects: 100% (7412/7412), 7.71 MiB | 4.84 MiB/s, done. Resolving deltas: 100% (5445/5445), done. $
続いて configure。
64bit 版をビルドする場合は prefix 指定を mingw32 → mingw64 に変更。
$ cd l-smash/ $ ./configure --prefix=/mingw32 (32bit版) $ ./configure --prefix=/mingw64 (64bit版はこっち)
generating config.mak ...
SRCDIR = .
DESTDIR =
prefix = /mingw32
exec_prefix = ${prefix}
bindir = ${exec_prefix}/bin
libdir = ${exec_prefix}/lib
includedir = ${prefix}/include
CC = gcc
AR = ar
LD = gcc
RANLIB = ranlib
STRIP = strip
STATICLIBNAME = liblsmash.a
STATICLIB = liblsmash.a
SHAREDLIBNAME = liblsmash-2.dll
SHAREDLIB =
IMPLIB = liblsmash.dll.a
CFLAGS = -Os -ffast-math -Wshadow -Wall -std=c99 -pedantic -I. -I. -D__USE_MINGW_ANSI_STDIO=1 -fexcess-precision=fast
LDFLAGS = -L. -Wl,--large-address-aware
SO_LDFLAGS =
LIBS = -lm
LIBARCH = i386
DEFNAME = liblsmash-2.def
SLIB_CMD = sed -i "s/ @[^ ]*//" $(DEFNAME); dlltool -m $(LIBARCH) -d $(DEFNAME) -l lsmash.lib -D $(SHAREDLIBNAME)
configure finished
type 'make' : compile library and tools
type 'make install' : install all into system
type 'make lib' : compile library only
type 'make install-lib' : install library and header into system
$ビルド。ライブラリだけでいいので、ターゲットは lib を指定します。
$ make lib -j15 j15 は環境に合わせて適当に gcc -c -Os -ffast-math -Wshadow -Wall -std=c99 -pedantic -I. -I. -D__USE_MINGW_ANSI_STDIO=1 -fexcess-precision=fast -o common/alloc.o common/alloc.c gcc -c -Os -ffast-math -Wshadow -Wall -std=c99 -pedantic -I. -I. -D__USE_MINGW_ANSI_STDIO=1 -fexcess-precision=fast -o common/bits.o common/bits.c gcc -c -Os -ffast-math -Wshadow -Wall -std=c99 -pedantic -I. -I. -D__USE_MINGW_ANSI_STDIO=1 -fexcess-precision=fast -o common/bytes.o common/bytes.c (省略) gcc -c -Os -ffast-math -Wshadow -Wall -std=c99 -pedantic -I. -I. -D__USE_MINGW_ANSI_STDIO=1 -fexcess-precision=fast -o core/timeline.o core/timeline.c gcc -c -Os -ffast-math -Wshadow -Wall -std=c99 -pedantic -I. -I. -D__USE_MINGW_ANSI_STDIO=1 -fexcess-precision=fast -o core/write.o core/write.c ar rc liblsmash.a common/alloc.o common/bits.o common/bytes.o common/list.o common/multibuf.o common/osdep.o common/utils.o codecs/a52.o codecs/alac.o codecs/description.o codecs/dts.o codecs/h264.o codecs/hevc.o codecs/id.o codecs/mp4sys.o codecs/mp4a.o codecs/mp4v.o codecs/nalu.o codecs/qt_wfex.o codecs/vc1.o codecs/wma.o importer/a52_imp.o importer/adts_imp.o importer/als_imp.o importer/amr_imp.o importer/dts_imp.o importer/importer.o importer/isobm_imp.o importer/mp3_imp.o importer/nalu_imp.o importer/vc1_imp.o importer/wave_imp.o core/box.o core/box_default.o core/box_type.o core/chapter.o core/file.o core/fragment.o core/isom.o core/meta.o core/print.o core/read.o core/summary.o core/timeline.o core/write.o ranlib liblsmash.a $
ビルドされたライブラリのインストール。
$ make install-lib install -d /mingw32/include install -m 644 ./lsmash.h /mingw32/include install -d /mingw32/lib/pkgconfig install -m 644 liblsmash.pc /mingw32/lib/pkgconfig install -m 644 liblsmash.a /mingw32/lib $ cd ~ $
これで L-SMASH 入り x264 のビルド環境ができあがり。
x264 のビルド
あとは 公式の git リポジトリ から x264 のソースを clone してきてビルドするだけ。
公式 git リポジトリからソースを clone する。
$ git clone http://code.videolan.org/videolan/x264.git Cloning into 'x264'... warning: redirecting to https://code.videolan.org/videolan/x264.git/ remote: Enumerating objects: 22359, done. remote: Counting objects: 100% (22359/22359), done. remote: Compressing objects: 100% (3848/3848), done. remote: Total 22359 (delta 18548), reused 22258 (delta 18468), pack-reused 0 Receiving objects: 100% (22359/22359), 5.20 MiB | 1.23 MiB/s, done. Resolving deltas: 100% (18548/18548), done. $
configure。 host オプション付けないと妙な exe ができるので注意。
Commit 71ed44c7 でビット深度 10bit, 8bit 両対応のバイナリがデフォルトになったので、ビット深度設定オプション --bit-depth は不要に。
64bit 版をビルドする場合は host 指定を i686-w64-mingw32 → x86_64-w64-mingw32 に変更する。
$ cd x264/ $ ./configure --extra-cflags="-pipe -march=native" --extra-ldflags="-static -static-libgcc" --enable-strip --host=i686-w64-mingw32 (32bit版) $ ./configure --extra-cflags="-pipe -march=native" --extra-ldflags="-static -static-libgcc" --enable-strip --host=x86_64-w64-mingw32 (64bit版) platform: X86 64bit版では X86_64 byte order: little-endian system: WINDOWS cli: yes libx264: internal shared: no static: no asm: yes interlaced: yes avs: avisynth lavf: no ffms: no mp4: lsmash ここが lsmash になっているか確認 gpl: yes thread: win32 opencl: yes filters: crop select_every lto: no debug: no gprof: no strip: yes PIC: no bit depth: all chroma format: all You can run 'make' or 'make fprofiled' now. $
make する。何かしらの動画を使って最適化する場合は make fprofiled を使う。
ここでは、そこまでこだわってないので普通に make します。
$ make -j15 j15 オプションは環境に応じて(ry cat common/opencl/x264-cl.h common/opencl/bidir.cl common/opencl/downscale.cl common/opencl/intra.cl common/opencl/motionsearch.cl common/opencl/subpel.cl common/opencl/weightp.cl | ./tools/cltostr.sh common/oclobj.h dependency file generation... windres --target=pe-i386 -I. -o x264res.o x264res.rc (省略) gcc-ranlib libx264.a gcc -o x264.exe x264res.o x264.o autocomplete.o input/input.o input/timecode.o input/raw.o input/y4m.o output/raw.o output/matroska.o output/matroska_ebml.o output/flv.o output/flv_bytestream.o filters/filters.o filters/video/video.o filters/video/source.o filters/video/internal.o filters/video/resize.o filters/video/fix_vfr_pts.o filters/video/select_every.o filters/video/crop.o input/avs.o output/mp4_lsmash.o filters/video/cache-8.o filters/video/depth-8.o input/thread-8.o filters/video/cache-10.o filters/video/depth-10.o input/thread-10.o libx264.a -L/mingw32/lib -llsmash -lm -lshell32 -m32 -static -static-libgcc -Wl,--large-address-aware -Wl,--dynamicbase,--nxcompat,--tsaware -s $
動作確認する。
$ ./x264 --version x264 0.160.3009 4c9b076 built on Jun 20 2020, gcc: 10.1.0 x264 configuration: --chroma-format=all libx264 configuration: --chroma-format=all x264 license: GPL version 2 or later $
exit して msys をインストールしたフォルダの home\(ユーザ名)\x264\x264.exe を適当な場所に移動なりコピーするなりすればできあがり。
それにしても 2017年だと -j3 だったのが -j15 になって隔世感ある。
続・SameSite指定されたCookieはCORS fetch時にどう働くか
まとめ
- 最近のブラウザは新しい Cookie 規格 RFC6265bis になってる
- Cookie の SameSite の判定は RFC6265bis Section 5.2 にある「Registrable Domain」の合致で判定される
- 「Registrable Domain」より前の部分は見てない
A request is "same-site" if its target's URI's origin's registrable domain is an exact match for the request's client's "site for cookies", or if the request has no client.
- 例えば
- www.example.com から api.example.com を fetch → 「Registrable Domain」が合致するので「Same-Site」
- www.foobar.com から api.example.com を fetch → 「Registrable Domain」が違うので「Cross-Site」
| SameSite判定 | Set-Cookie時のSameSiteの指定 | リクエストにCookieが… |
|---|---|---|
| Same-Site | none | ○付く |
| Same-Site | lax | ○付く |
| Same-Site | strict | ○付く |
| Cross-Site | none | ○付く |
| Cross-Site | lax | ×付かない |
| Cross-Site | strict | ×付かない |
- ここでの「Same-Site」「Cross-Site」はあくまでも Cookie に対しての話なので、 CORSリクエストのそれとは分けて考えること。
- サブドメインが違うだけの CORS fetch では SameSite=lax/strict 指定の Cookie もリクエストに付加されるので、そういう構成がとれる場合は API の認証に SameSite=lax/strict な Cookie が使える。
- めっちゃ参考になった
- RFC6265bis の存在を知った
- RFC6265bis Draft 06
経緯とか
昨日すっとぼけたことを書いていたトピック の続きとして、よく見かけるサイトURLが www.example.com、 API用URLが api.example.com のようなサブドメインが違うだけという構成を試してみたところ、Set-Cookie に domain=example.com 指定もしていないのに APIサーバに Cookie が送られてる……という謎に遭遇して調べ回った結果が↑のまとめの通り。
確認するには、ブラウザアクセス用のドメインとして www.example.com を hosts に追加(テストが済んだら削除すること)。
127.0.0.1 apitest.example.com
+127.0.0.1 www.example.com
この状態で、ブラウザで http://www.example.com:5500/ を開くと、 http://www.example.com:5500/ のサイトから http://apitest.example.com:3000/ に CORS fetch リクエストをすることになるので、SameSite のセレクトボックスから strict や lax を選んで Cookie を SET すると、 GET, POST には Cookie が付かないはず……が、 msg = undefined にはならず、入力したテキストが表示される。
デベロッパーツールで確認してもちゃんとリクエストには Cookie が付いている。
「もしかしてサブドメインが無視されてる?」と考え、 hosts にちょっと違うドメインを追加。
127.0.0.1 apitest.example.com
127.0.0.1 www.example.com
+127.0.0.1 www.example2.com
その上で http://www.example2.com:5500/ から strict / lax で Cookie SET すると、その後の GET/POST には Cookie は付かず。
ブラウザのバグという線は限りなく低いので調べていった結果、上記のサイトに出会った次第。
SameSite指定されたCookieはCORS fetch時にどう働くか
まとめ
2020/05/17 修正
fetch などを使った CORS リクエストにおいて、API サーバから SameSite 設定付きで Set-Cookie が返された場合、以降の CORS リクエストに Cookie は付くのかどうか → SameSite=none の場合のみ Cookie が付く。
ただし、サブドメイン部だけが異なるドメイン間での CORS の場合、lax/strict でも Cookie が付く → もうちょっと調べたトピック 参照
以下の通り、lax や strict を指定された Cookieは 別ドメインに対する CORS fetch リクエストには付かない。
| SameSite | Cookie |
| none | ○付く |
| lax | ×付かない |
| strict | ×付かない |
CORS で Cookie を使う場合、 SameSite=none にしつつ API の応答に Access-Control-Allow-Credentials: true を付けたり、 fetch 時のオプションに credentials: 'include' 付けたりと、CORSの仕様に沿う必要もある。
また、ブラウザの設定でサードパーティーCookieがブロックされている場合、 SameSite の指定に関係なく Cookie は付かない(Set-Cookieが無視されるのでブラウザに記憶されない)。
この挙動を考えると、Cookie認証なAPI サーバを別ドメインにする構成では SameSite=none の指定が必須になるわけですね。
以下打ち消し線部分は間違い
Cookie の挙動と Same Origin Policy を混同してました。
Cookie の場合、ドメイン名のみで識別されスキーマとポート番号は無視されるので、APIサーバを別ポートで動かしただけでは CORS が必要になるけれども Cookie の挙動は同一ドメイン時と同じ、という状態でのテストになっていた。という次第。
(そりゃ全部Cookie付くわなorz)
fetch などを使った CORS リクエストにおいて、API サーバから SameSite 設定付きで Set-Cookie が返された場合、以降の CORS リクエストに Cookie は付くのかどうか → 付く。
| SameSite | Cookie |
| none | ○ |
| lax | ○ |
| strict | ○ |
ただし、API サーバの応答に Access-Control-Allow-Credentials: true を付けたり、 fetch 時のオプションに credentials: 'include' 付けたりと、CORS 下で Cookie を使う仕様に沿う必要はある。
検証に使った適当なコード
簡易API サーバ
指定された条件で Set-Cookie を発行する API と、リクエスト中の Cookie を取得して返す API の簡易APIサーバ。
別ドメインに見せかけるため、 hosts ファイルに以下を追加して apitest.example.com でアクセスする(検証が終わったら削除する)。
127.0.0.1 apitest.example.com
/api/ に { 'msg': 'hoge', 'samesite': 0} みたいな JSON を POST すると Set-Cookie 入りのレスポンスを返す。
/api/cookie/ に POST したり GET したりすると、リクエスト中の Cookie の中身を JSON で返す。
// cors_api.js const express = require('express'); const cookieParser = require('cookie-parser'); const cors = require('cors'); const app = express(); app.use(cookieParser()); app.use(express.json()); // application/json // see https://expressjs.com/en/resources/middleware/cors.html#configuration-options const cors_options = { origin: true, // Access-Control-Allow-Origin: <Origin> credentials: true // Access-Control-Allow-Credentials: true } // set cookie to response app.options('/api/', cors(cors_options)); app.post('/api/', cors(cors_options), (req, res) => { console.log(req.cookies); const msg = req.body.msg; const samesite = req.body.samesite == 0 ? 'none' : req.body.samesite == 1 ? 'lax' : 'strict'; res.cookie('msg', msg, { httpOnly: true, sameSite: samesite }); res.json({ msg : `msg=${msg}; samesite=${samesite}`}); }); // get cookie from request const getCookie = (req, res) => { console.log(req.cookies); const msg = req.cookies['msg']; res.json({ msg : `msg=${msg}`}); }; app.options('/api/cookie/', cors(cors_options)); app.get('/api/cookie/', cors(cors_options), getCookie); app.post('/api/cookie/', cors(cors_options), getCookie); // start server app.listen(3000, 'localhost', () => console.log('Listening on port 3000'));
ドライバHTML
簡易APIサーバの API を叩くドライバHTMLを、VS Code の LiveServerなどの適当なWebサーバ介して localhost ドメインとしてブラウザで開く。
テキストボックスに Cookie に設定する文字列を入れ、その後ろのセレクトボックスは Cookie に設定する SameSite の種類を選ぶ。SET ボタンを押すと /api/ が叩かれて Set-Cookie 付きのレスポンスが得られる。
そして、GETボタンやPOSTボタンを押すと、それぞれのメソッドで /api/cookie/ が叩かれて、それらのリクエストに付いてくる Cookie の中身が表示される。
msg=undefined となったり、テキストボックスに入れた文字列と違うものが表示された場合はサーバ側で Cookie が取得できていないことを表す。
<!DOCTYPE html> <html> <body> <input type="text" id="msg"></input> <select id="samesite"> <option value="0">none</option> <option value="1">lax</option> <option value="2">strict</option> </select> <button id="s">SET</button> <button id="s_get">GET</button><button id="s_post">POST</button><span id="ans"></span> <script> document.getElementById('s').addEventListener('click', async (e) => { e.preventDefault(); const msg = document.getElementById('msg').value; const samesite = document.getElementById('samesite').value * 1; const req = { msg, samesite }; res = await fetch("http://apitest.example.com:3000/api/", { method: 'POST', body: JSON.stringify(req), mode: "cors", credentials: 'include', headers: { "Content-Type": "application/json; charset=utf-8", } }); json = await res.json(); document.getElementById('ans').innerText = json.msg; }); document.getElementById('s_get').addEventListener('click', async (e) => { e.preventDefault(); res = await fetch("http://apitest.example.com:3000/api/cookie/", { method: 'GET', mode: "cors", credentials: 'include'}); json = await res.json(); document.getElementById('ans').innerText = json.msg; }); document.getElementById('s_post').addEventListener('click', async (e) => { e.preventDefault(); res = await fetch("http://apitest.example.com:3000/api/cookie/", { method: 'POST', mode: "cors", credentials: 'include'}); json = await res.json(); document.getElementById('ans').innerText = json.msg; }); </script> </body> </html>