The Man Who Fell From The Wrong Side Of Sky:2019年1月分

2019/1/4(Fri)

[Windows] PowerShellで生活するために - Invoke-WebRequest コマンドレット編(その1)

ここ数年脱UNIX(TM)文化を志してタッパーウェア捨てたり美容院を変えたりし、普段使いのシェルもCygwinからPowerShellにして頑張ってるんですがまぁハマりどころが多くてキレそうです(憤怒)。

まず最初に書いておくとPowerShellをわざわざ使うなんてのは正気の沙汰じゃない、よりにもよって暗黒期の横浜ベイスターズに自分からFA入団するようなものだ。

みんなプロになりたいんだろ、チャンスはあるよ。でも横浜だけはやめとけよ (by 門倉健)

という箴言を心に刻みこんで、PythonでもRubyでもなんでもいいからまともなプロと呼べる球団へ入ろう。Perlはうん…

ハマりどころの例を挙げると、ウェブページのスクレイピングをしたいという時、UNIX(TM)環境ならwget(1)やらcurl(1)、そしてNなんとかBSDならftp(1)あたりを使うところだけど *1、PowerShellではいろいろと問題がある。

こいつらと同じことをしたければPowerShell 3.0以降では Invoke-WebReqestというコマンドレットがある(ご丁寧にwgetがエイリアスとなってる、なおオプションに互換性は皆無だ)。 ところがWindows 7やWindows Server 2008 R2に標準添付のPowerShellのバージョンは2.0なのでバージョンアップが必要となる。さもなくば.Net Frameworkの System.Net.WebClientをCOM経由で操作せざるをえない羽目になる。

ちなみにPowerShellのバージョンアップはWindows Management Framework(WMF)を別途インストールすればいいだけ、最新は WMF5.1だ。

ところがそれだけじゃ終わらない、Invoke-WebRequestにはいくつか初心者には判りにくいハマりどころがある。

@スクリプト実行ポリシーの設定が必要

これはPowerShell自体の問題なんだけど、Invoke-WebRequestを使ってウェブページをファイルに保存したいだけであればプロンプトで

PS> C:\Users\tnozaki> Invoke-WebRequest 'https://example.com/' -OutFile unko.html

と叩くだけなんだけど、リクエストがPOSTとかリファラとかクッキーとか認証とか必要だったり、また取得したHTMLを整形した上で保存するみたいな後処理が必要になると、これはもうスクリプト化したくなる。

ところがPowerShellのデフォルトの設定はなんと「スクリプトはすべて実行禁止」なので

PS C:\Users\tnozaki> .\unko.ps1
.\unko.ps1 : このシステムではスクリプトの実行が無効になっているため、ファイル C:\Users\tnozaki\unko.ps1 を読み込むことができません。
詳細については、「about_Execution_Policies」(http://go.microsoft.com/fwlink/?LinkID=135170) を参照してください。
発生場所 行:1 文字:1
+ .\unko.ps1
+ ~~~~~~~~~~
  + CategoryInfo     : セキュリティ エラー: (: ) []、PSSecurityException
  + FullyQualifiedErrorId : UnauthorizedAccess

となり実行すら許されぬというめんどくささ、はーつっかえもうやめたらこの仕事。

まず現在の設定を確認するにはGet-ExecutionPolicyコマンドレットを使用する。

PS C:\Users\tnozaki> Get-ExecutionPolicy
Restricted

デフォルトでは「Restricted」なので全面禁止、これ変更するためにはまず管理者権限でPowerShellを起動しないとならない。

ということで管理者権限が無い人はここでグッバイ、自分の書いたスクリプトすら実行できないって馬鹿じゃねぇの。

ということで管理者権限でPowerShellを起動しポリシーを変更するためにSet-ExecutionPolicyコマンドレットを実行する、設定可能な引数は以下の通り。

実行場所 ローカル リモート
署名 あり なし あり なし
Restricted × × × ×
AllSigned × ×
RemoteSigned ×
Unrestricted △(警告)
Bypass

これらの意味について細かい説明をすると長くなるのでまたいずれ回を改めて書く。

とりあえず実行したければSet-ExecutionPolicyコマンドを使用し、署名すんのもめんどいので「RemoteSigned」くらいまで緩めとく。

PS C:\Users\tnozaki> Set-ExecutionPolicy RemoteSigned

Execution Policy Change
The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might
expose you to the security risks described in the about_Execution_Policies help topic at
http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "N"):

変更していいか問われるので、YあるいはAとでも答えておく。

@Internet Explorer 11 の設定が必要

しかしこれだけじゃまだ動かない、Invoke-WebRequestは内部的にIE11をCOMオブジェクトとして動かしてるだけなので、そちらの設定が未了だと動かないのですわ。

なので一度もIE11を起動せずにChromeやFirefoxをスタンドアロンインストーラーで入れて使ってる人はいきなりここでハマる。 またWindows 10環境ではOS標準ブラウザがMicrosoft Edgeに変更されたのでIE11を一度も起動したことの無い可能性が高いのだけど、PowerShellが呼ぶのはあくまでEdgeでなくIE11。やっぱりハマるわけですわ。

ということでめんどくさいけど一度はIE11を起動して初回起動時に表示される「Internet Explorer 11 の設定」ダイアログで「お勧めのセキュリティと互換性の設定を使う」あるいは「推奨設定を使用しない」を選択して初期設定を済ませておく必要がある。

@TLS1.2 対応が必要

困ったことにInvoke-WebRequestはデフォルトで今時TLSv1.2に対応していない、当チラシの裏ですら TLSv1とv1.1を無効にするご時勢だというのに…

よって

if (-not ([Net.ServicePointManager]::SecurityProtocol -band [Net.SecurityProtocolType]::Tls12)) {
	[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
}

の3行を追加してセッション中でTLSv1.2を有効にする、あるいは KB2960358を適用して規定値を変更する必要がある(詳細については ここを読め)。

ちなみにKB2960358は月例のセキュリティおよび品質ロールアップには含まれていない上、Windows UpdateにもMicrosoft Update Catalogにも出てこないので前述のリンク先からダウンロードして手動適用すること。

@文字コード絡みのバグを抱えているので対策が必要

ここまでの設定でとりあえずInvoke-WebRequestは使えるようになるのだけど、文字コード周りに致命的なバグを抱えていてその対策が必要となる。

というのも、サーバーがレスポンスヘッダでcontent-typeにcharsetを返さない場合、Invoke-WebRequestはコンテンツのBOMやHTMLのmetaタグで指定されたcharsetを一切検証することなくISO-8859-1(あるいはASCII-8BIT)として扱うので文字化けするのだ。 もう長いことIssueになってるけど直らないということは直す気が無いということと思われる。

これ明示的に文字コードを指定する方法も存在しないので、コンテンツをいちどISO-8859-1からバイト列に戻した上でBOMやHTMLのmetaタグから正しい文字コードを取得し、もういちど文字列へ変換し直す必要がある。

これについては記事が長くなるのでまた次回コードつきで詳細に解説する予定。

*1:telnet(1)でhttp喋りますとかネタでも寒いから、openssl(1)使ってhttpsも喋れますとかもっと寒いから。

2019/1/5(Sat)

[Windows] PowerShellで生活するために - Invoke-WebRequest コマンドレット編(その2)

前回の続き、実際にコードを交えて解説していく。

以下のPowerShellによるコードは

というスクレイピングの初歩中の初歩ちゅーもの。

$res = Invoke-WebRequest 'https://www.hi-matic.org/' -Method Get
$res.AllElements | Where-Object { $_.tagName -eq 'h1'} | ForEach-Object {
	Write-Host $_.innerText
}

しかし困ったことに実行してもエラーになる

PS C:\Users\tnozaki> C:\Users\tnozaki\unko.ps1
Invoke-WebRequest : 接続が切断されました: 送信時に、予期しないエラーが発生しました。。
At C:\Users\tnozaki\unko.ps1:1 char:8
+ $res = Invoke-WebRequest 'https://www.hi-matic.org/' -Method Get
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
PS C:\Users\tnozaki> 

これはPowerShellというか.Net FrameworkがTLSv1.2にデフォルトで未対応なのが原因、よって3行ほどの対策コードを追加する。

if (-not ([Net.ServicePointManager]::SecurityProtocol -band [Net.SecurityProtocolType]::Tls12)) {
	[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
}
$res = Invoke-WebRequest 'https://www.hi-matic.org/' -Method Get
$res.AllElements | Where-Object { $_.tagName -eq 'h1'} | ForEach-Object {
	Write-Host $_.innerText
}

そんで改めて実行すると、エラーは起きないものの今度はタイトルが化けるのですな。

PS C:\Users\tnozaki> C:\Users\tnozaki\unko.ps1
チラシの裏

この原因はInvoke-WebRequestのバグで

という動作をする為だ。

この対策はちょっとめんどくさいのだけども、なるべくコードを短くかつ外部ライブラリなどへの依存なくかつ実用に足るものを書くとすると以下のようなコードになる。

if (-not ([Net.ServicePointManager]::SecurityProtocol -band [Net.SecurityProtocolType]::Tls12)) {
	[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
}
$res = Invoke-WebRequest 'https://www.hi-matic.org/' -Method Get
$content = $res.Content
if ($res.Headers['content-type'] -notmatch "charset *=") {
	$bytes = [System.Text.Encoding]::GetEncoding('ISO-8859-1').GetBytes($content)
	$encoding = 'ISO-8859-1'
	if (($bytes.Length -ge 4) -and ($bytes[0] -eq 0x00) -and ($bytes[1] -eq 0x00) -and ($bytes[2] -eq 0xfe) -and ($bytes[3] -eq 0xff)) {
		$encoding = 'UTF-32BE'
	} elseif (($bytes.Length -ge 4) -and ($bytes[0] -eq 0xff) -and ($bytes[1] -eq 0xfe) -and ($bytes[2] -eq 0x00) -and ($bytes[3] -eq 0x00)) {
		$encoding = 'UTF-32LE'
	} elseif (($bytes.Length -ge 2) -and ($bytes[0] -eq 0xfe) -and ($bytes[1] -eq 0xff)) {
		$encoding = 'UTF-16BE'
	} elseif (($bytes.Length -ge 2) -and ($bytes[0] -eq 0xff) -and ($bytes[1] -eq 0xfe)) {
		$encoding = 'UTF-16LE'
	} elseif (($bytes.Length -ge 3) -and ($bytes[0] -eq 0xef) -and ($bytes[1] -eq 0xbb) -and ($bytes[2] -eq 0xbf)) {
		$encoding = 'UTF-8'
	} else {
		# XXX TODO: consider some non US-ASCII compatible encoding such as UTF-7, HZ, and so on.

		# assume US-ASCII compatible encoding, use DOM to extract meta charaset.
		$res.AllElements | Where-Object { $_.tagName -eq 'meta' } | ForEach-Object {
			if (Get-Member -InputObject $_ -Name 'charset' -Membertype NoteProperty) {
				$encoding = $_.charset
			} elseif ((Get-Member -InputObject $_ -Name 'http-equiv' -Membertype NoteProperty) -and ($_.'http-equiv' -eq 'content-type')) {
				if ($_.content -match 'charset *= *(?<encoding>.+)') {
					$encoding = $Matches.encoding
				}
			}
		}
	}
	$content=[System.Text.Encoding]::GetEncoding($encoding).GetString($bytes)
}
# DOM is immutable, there's no way to fix its wrong encoding.
# anyway, let's create new one via MSHTML Object.
$html = New-Object -ComObject 'HTMLFile'
try {
	$html.write([System.Text.Encoding]::Unicode.GetBytes($content))
} catch {
	# MS Office may affect MSHTML's behavior, use IHTMLDocument2_write instead.
	$html.IHTMLDocument2_write([System.Text.Encoding]::Unicode.GetBytes($content))
}
# Where-Object doesn't work, use Old-School DOM API, 
$html.body.getElementsByTagName('h1') | ForEach-Object {
	Write-Host $_.innerText
}

ポイントは以下の通り。

@応答ヘッダ中からcontent-typeを取得し、charsetが指定されてるかをチェックする

この部分ね、応答ヘッダへのアクセスはInvoke-WebRequestの戻り値(HtmlWebResponseObject型)のHeadersプロパティから可能。

if ($res.Headers["content-type"] -notmatch "charset *=") {
...
}

雑に正規表現でひっかけてるだけなのでもっとちゃんとしたコード書きたい人は勝手に苦労してどうぞ。

ちなみに-match/-notmathは-imatch/-inotmatchと同義、PowerShellはデフォルトはignore caseという世にも恐ろしいアレなので厳密に区別したければ-cmatch/-cnotmatchを使う、馬鹿じゃねぇの。 また文字列クラスにはワイド文字も含まれてるので、例えば「\s」ならSPACE(U+0020)だけでなくIDEOGRAPHIC SPACE(U+3000)なんかにもマッチする。こいつらの落とし穴的な話はまたいずれ正規表現編でも書きますかね。

@ISO-8859-1と解釈されたまま変換されてしまったPowerShellの文字列(UTF-16)をバイト列に戻す

これはこの部分、HTMLドキュメントをDOMなどのオブジェクトでなく文字列で抜くにはHtmlWebResponseObjectのContentプロパティを使う。 そしてiconv(1)的な文字コード変換のコマンドレットは用意されてないので、.Net Frameworkの System.Text.Encodingを使ってUTF-16からバイト列に戻して差し上げる。

$content = $res.Content
…
	$bytes = [System.Text.Encoding]::GetEncoding('ISO-8859-1').GetBytes($content)

@バイト列からBOMによって文字コード判定を行う

今度はこの部分やね

	$encoding = 'ISO-8859-1'
	if (($bytes.Length -ge 4) -and ($bytes[0] -eq 0x00) -and ($bytes[1] -eq 0x00) -and ($bytes[2] -eq 0xfe) -and ($bytes[3] -eq 0xff)) {
		$encoding = 'UTF-32BE'
	} elseif (($bytes.Length -ge 4) -and ($bytes[0] -eq 0xff) -and ($bytes[1] -eq 0xfe) -and ($bytes[2] -eq 0x00) -and ($bytes[3] -eq 0x00)) {
		$encoding = 'UTF-32LE'
	} elseif (($bytes.Length -ge 2) -and ($bytes[0] -eq 0xfe) -and ($bytes[1] -eq 0xff)) {
		$encoding = 'UTF-16BE'
	} elseif (($bytes.Length -ge 2) -and ($bytes[0] -eq 0xff) -and ($bytes[1] -eq 0xfe)) {
		$encoding = 'UTF-16LE'
	} elseif (($bytes.Length -ge 3) -and ($bytes[0] -eq 0xef) -and ($bytes[1] -eq 0xbb) -and ($bytes[2] -eq 0xbf)) {
		$encoding = 'UTF-8'
	} else {
		…
	}

まずBOMで判定可能なのは先頭バイトが

  • 0x00 0x00 0xfe 0xff … UTF-32BE
  • 0xff 0xfe 0x00 0x00 … UTF-32LE
  • 0xfe 0xff … UTF-16BE
  • 0xff 0xfe … UTF-16LE
  • 0xef 0xbb 0xbf … UTF-8 + BOM

かどうかチェックすればよい。

@Metaタグのcharsetから文字コード判定を行う

この部分ね。

	$encoding = 'ISO-8859-1'
…
		# XXX TODO: consider some non US-ASCII compatible encoding such as UTF-7, HZ, and so on.

		# assume US-ASCII compatible encoding, use DOM to extract meta charaset.
		$res.AllElements | Where-Object { $_.tagName -eq 'meta' } | ForEach-Object {
			if (Get-Member -InputObject $_ -Name 'charset' -Membertype NoteProperty) {
				$encoding = $_.charset
			} elseif ((Get-Member -InputObject $_ -Name 'http-equiv' -Membertype NoteProperty) -and ($_.'http-equiv' -eq 'content-type')) {
				if ($_.content -match 'charset *= *(?<encoding>.+)') {
					$encoding = $Matches.encoding
				}
			}
		}

本当はBOMでの判定の後にさらにUTF-7やHZなどのUS-ASCII非互換な文字コードの判定も必要なんだけど、そこまでするメリットがこの2019年という時代に存在するとは思えないので割愛ですな。 ということで極力手を抜くためにUS-ASCII互換と仮定し、HTMLのパースも文字化けしたままでもmeta charsetくらいはぶっこ抜けるのでそのまま応答中のDOMを操作する。

ここで自称関数型のPowerShellっぽくストリームとフィルタを使ってDOMを操作してるけど、旧来のDOM APIの方使ってる人の方が多いよね。書き直すとこう、AllElementsでなくParsedHtmlプロパティを使う。

		$res.ParsedHtml.getElementsByTagName('meta') | ForEach-Object {
			...
		]

なんとこっちの方が短く書ける上に下手すると性能も良かったりする(PowerShellのパイプってクソ遅い)、やっぱり馬鹿じゃねえのこの言語。

@正しい文字コードを指定して再びバイト列から文字列に変換する

ここ、文字列に戻す時もやっぱりSystem.Text.Encodingを使う。

	$content=[System.Text.Encoding]::GetEncoding($encoding).GetString($bytes)

@新たにDOMツリーを作成する。

これ困ったことにHtmlWebResponseObjectはどうやら変更不可かつインスタンス化不可なようで、正しく文字コード変換した結果を戻す方法が無い。 なので、代わりにMSHTML.HTMLFileのDOM APIをCOM Object経由で使う、それならもうVBScriptでええやん…

コードは以下の部分。

# DOM is immutable, there's no way to fix its wrong encoding.
# anyway, let's create new one via MSHTML Object.
$html = New-Object -ComObject 'HTMLFile'
try {
	$html.write([System.Text.Encoding]::Unicode.GetBytes($content))
} catch {
	# MS Office may replace MSHTML, use IHTMLDocument2_write instead.
	$html.IHTMLDocument2_write([System.Text.Encoding]::Unicode.GetBytes($content))
}
# Where-Object does'nt work, use Old-School DOM API, 
$html.body.getElementsByTagName('h1') | ForEach-Object {
	Write-Host $_.innerText
}

謎のtry catchがあるけれど、これ恐ろしいことにMSHTML.HTMLFileにはいくつかのバージョンがあるようで、MS Officeがインストールされている環境だと writeを呼出すと以下のエラーが出てしまう。

PS C:\Users\tnozaki> C:\Users\tnozaki\unko.ps1
Exception calling "write" with "1" argument(s): "種類が一致しません。
"
At C:\Users\tnozaki\unko.ps1:40 char:5
+     $html.write([System.Text.Encoding]::Unicode.GetBytes($content))
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : COMException
 
You cannot call a method on a null-valued expression.
At C:\Users\tnozaki\unko.ps1:46 char:1
+ $html.body.getElementsByTagName('h1') | ForEach-Object {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

よってこの例外をcatchして代わりにIHTMLDocument2_writeの方を使うというワークアラウンドが必要なんですわ。

そんで最後の部分、MSHTML.HTMLFileはCOM Objectなので旧来のDOM APIによる操作しかできないので、PowerShellらしいパイプとストリームが使えない。 それならやっぱりVBScript使えばいいんじゃねぇかクソが。

ここまでやってようやく文字化けせずに表示がでる

PS C:\Users\tnozaki> C:\Users\tnozaki\unko.ps1
チラシの裏

@結論

なんでたかがスクレイピングの初歩の初歩でこんだけ苦労するんですかね(しろめ)。

2019/1/6(Sun)

[写真] 部分日食

2012年の金環日食の時といい曇り空ばっかなんやな、その前の2009年だかの部分日食も雨降ってたような記憶がある。

これじゃ出番が数年に一度しかないクッソ高価な日食用のNDフィルター買ったやつは敗北者じゃけぇ、厚く垂れこめた雲の前にフィルター外して雲が薄くなるのを待つの、実に空虚じゃありゃせんか?

つーことで写真は2012年の時のやつ、ワイは諦めて出勤してたので家族撮影のもの。

今日も撮影準備はしてたんだけど、朝9時頃に空模様と寒さを鑑みてこれなら暖かくして寝てた方がマシということで断念、生きてられたら次の今年12/26の日入帯食に挑戦やね。

2019/1/8(Tue)

[新年] あけましておめでとうございます

うちではデヴィッド・ボウイ暦を採用してるのでグレゴリオ暦の1月8日がお正月でございます。

Of cource there's a chance.

2019/1/11(Fri)

[クラウド] Amazon Prime Videoの画質が悪い場合にすべきたったひとつの事

旧サザエさんとかほんとどうでもええんやけど、The Grand Tour: Season 3まで残り一週間で年に一度のお楽しみ待ちきれませんな。

あと高い城の男のシーズン3もくるのか、アメリカらしい無節操な引き延ばしがだるくてシーズン1よりあとまだ観てないんですけどね。

んで表題の件、これはAmazonらしいセコさといおうか「文句言わない客には最低のもてなしをする」パターンで、動画品質で「最高画質」を選択してても画質が悪いのは仕様なんだよね。

なので以下のことをすると劇的に画質は改善します(鯖の混み具合によってはしないかも)。

ブラウザ拡張でお笑い芸人の汚いツラをスキップするのと同時にこのクレーム送信をするやつ作ればけっこう人気になると思う(ぉ

まぁKindleなどのタブレット端末持ってるならローカルにダウンロードした上で視聴するのが 一番マシだとおもう、パソコンもブラウザももはや老人専用ツールなのだ。

2019/1/13(Sun)

[やきう] ぶらんどん

ロッテが元DeNAブランドン・マン投手を獲得、横浜愛され系クソ助っ人外国人としてロマックに次ぐ謎の人気を誇るぶらんどん帰ってくるのか、久しぶりにやきう観るしかナイジャー・モーガン。

つーことで来年はロッテ応援するのでよろしく、ところでロッテはKBOのレジェンド級強打者ロメクも獲得しませんかね?

2019/1/14(Mon)

[自宅システム管理者] 中華製ネットワーク機器

つい最近 Winyaoという謎メーカーを知ったのだけど、いろいろ妖しいネットワーク製品あるなぁ、USB2.0/3.0なSFP Fibre Channel Adapterって一体どういう需要なんですかね…

ここのPCI-E Gen2.0 x1に刺さるDual Port SFP Fiber Channel Adapterとかクソ遅そうだけど、x16が空いてないHP Microserver N54LのFC-SAN化にほんのちょっとだけ欲しい気がする、まぁスイッチ持ってないし結構高いので買う事はないのだけど。

2019/1/17(Thu)

[写真] アナモルフィックレンズ

以前6x12なんかのアスペクト比2:1なフォーマットで撮影できるカメラが欲しいという話を 書いたのだけど、よく考えるとこのアスペクト比ってシネマスコープの12:5(2.35:1)とほぼ一緒なのでそっち系の機材揃えるってのも手なんだよな。

このシネマスコープってやつは

という技術、その名の通り映画撮影で使われてるもの。

さすがに35mm用は業務用で買えるお値段じゃないのだけど、アマ向けの16mm用をマイクロフォーサーズに装着して撮影してる人も結構いるんだよね。

動画撮影も風景撮りとかシネマスコープだとパンせずに固定で撮っても映えるしちょっと欲しいんだよな、な金無。

どうやら最近は通常レンズの前面にとりつけるコンバーターがあって、4:3センサー用の倍率x2だけでなく16:9センサー用のx1.33もあるのよね、 SLR Magic Anamorphotとか。あと moondoglabsからiPhoneなんかのスマートフォン向けのアダプタもあったり。

ただアナモルフィックレンズは

といった問題点があるのだけども、画質に関するところは動画なら味になったり我慢できたりもするけど静止画だと厳しいかもしれん。

それにパノラマ写真はいまどきはデジタルを生かして Ricoh Thetaみたいに全周魚眼使った360度撮影、そしてSONYデジカメのスイングパノラマのようにパンしての複数枚撮影を補正編集する方がコストかからん風潮なので こっち方面のテクノロジーは今後もニッチのままなんだろう。

縮小光学系というとフォーカルレデューサーはフルサイズのイメージサークルをAPS-CやM4/3に縮小する Metabone Speed Boosterがヒットしたことで見直され、品質問わなければ中華製のあやしいのが1万も出せば買えるんだけどね。アナモルフィックアダプターも流行らんものかな。

自分でDIYするのなら凸円柱レンズよりもプリズム使った潜望鏡方式の方がコストかからんみたいではある、まぁそんな器用じゃないのでやらんが。

2019/1/18(Fri)

[写真] SHARP announced cheap 3000 USD 8k M4/3 camera

はえー SHARPがM4/3な8k動画カメラを3000ドルで出すのね、8kというと IMAXの70mmフィルムを粒状性の限界くらいの2900~4000dpiでスキャンしたのと同等の解像度なわけで、このレベルの撮影には数千万~億のお値段の特殊レンズとシビアなフォーカス合わせ技能が必要なのにそこは既成のM4/3マウントレンズって、そんな装備で大丈夫かイーノック。

つかM4/3自体は消費電力そして昨日書いたシネマスコープとの相性のいいアスペクト比ってのもあってAPS-Cやフルサイズよりよっぽど動画に優れてると思うし自分もメインで使ってるけど、レンズ能力的にもセンサーの画素ピッチ的にも解像度は4kでもオーバースペック気味で8kとか無意味ってレベルじゃねーぞ。

それに8kでRAWとか無理で圧縮かかるだろうし、それなら2k/4k RAWつーか下手するとFullHD RAWの方がよっぽど優れた絵が出てきそうな気がするよな。

つーことで自分ならタダで貰ったとしても売りとばしてGH5かBlackmagicそして差額で別の撮影道具を買いますわ、やっぱりSHARPはSHARPであった。

2019/1/19(Sat)

[クラウド] Amazon Prime Videoの不満点

画質については前回 書いたからええとして、レンタル期間はちょっと不満なんよね。

再生をいちど開始すると最後までまだ観ていなくても3日間でレンタル期間が終了してしまう。 3日間だとクソ映画を一時停止しながら我慢して完走しようとしても、だいたい見終る前に期限が切れちゃうんだよな。やっぱりクソ映画を観るなら一週間レンタルOKな物理レンタルビデオ店の方がいい、まぁ近所はほとんど絶滅してしまったのだけど。

というかクソ映画を観なければいいのだがクソ映画を観ないとクソ映画とは何かが語れなくなるのでクソ映画は定期的に補給しなければならない、クソ映画は必須栄養素とてもだいじ。

2019/1/21(Mon)

[写真] 月の裏側を観てみたいと空を見上げて君は呟く

もうスーパームーンといわれても食傷気味なんだけど撮ってきた。

ちなタイトルは Mwandishi/心繋いでの歌詞の一節より、月の写真撮ってる時はたいていこの曲を聴いてるんだけど(youtubeには無いのでいい曲だから気になる人は中古探して)、そういやちょうど今この月の裏側には中国の探査機おるんよなぁという思い。

思いかえすとニール・アームストロング氏が死去した後の中秋の名月を撮影してた時(動画は これ)もなんかエモい気分でしたね(語彙力)。

今回はKenko MZ-5000 1:8-16 f=650-1300mmという「ザ・安物・オブ・安物」な超望遠レンズで撮影、今でも中身同じレンズがSamyang/Neewer/Opteka銘で新品25k~35kくらい(中古なら相場は15~20k程度)で入手できると思う。ただしその金額を出す価値があるかというと大いに疑問のあるレンズで、撮影対象を月に限定したとしてもキットレンズの安物ズーム70-300mmで撮影してトリミングするよかわずかにマシというレベルやね。

自分は人気のないAマウントのものを数千円で数年前に入手したんだけど、そのお値段くらいなら手を出してもまぁええんじゃないかと。

ちなみにAマウント用といっても実際はTマウント + 変換アダプタなので他マウントでも使い回し可能、よってわざわざ相場の高いC/Nみたいな人気マウント用を買う必要はない。 Tマウントアダプターも中華製の安物なら数百円で買えるので、くれぐれも無駄金を使わないようにね…

2019/1/24(Thu)

[映画] John Lithgow/Pet Sematary

へぇ、ペットセメタリー再映画化するのね。

このトレーラーだと1989年版よりもスタンリー・キューブリック監督の映画「シャイニング」へのオマージュを多くのシーンで感じるのだけど、原作のスティーブン・キングって事ある毎にキューブリック版シャイニングを酷評してたはずなんだが(怒りのあまり自分でメガホンまでとった)、この監督も怒りを買いませんかね大丈夫?

2019/1/28(Mon)

[音楽] MIDI 2.0

いまさらいまどきのDTM環境に移行する気ゼロなので死ぬまでKAWAI Q-80EXとAKAI DR4d使い続けるよだし、その上いまさらMIDI 2.0といわれてもそうですか(無関心)なのだけど、SMF(Standard MIDI File)フォーマットの通称としてのMIDI(.mid)と混同してJASRACガーと暴れる謎の勢力を観察するのが楽しいからまあええか(ぉ

前世期にそろそろDTMに移行しようと思った時、ライブ等で気軽に持ち運べるようなノートPCとして買ったThinkPad 230Csに刺せるMIDIインタフェースって、TDK/E-MU MC8001(MW8232)というPCMCIAタイプのモノくらいしかなかったのだけど、こいつ選んだのが大失敗だったんよな。 このクソカードとんでもないことにWindows 95 OSR2以降だとドライバ非互換で、Windows98にアプデしたら動かんようになった上にアップデートなしにディスコンになってしまい金ドブもいいところであった。

この時の怒りがあって絶対にPCで音楽はやらねぇとなった上に、Windowsで駄目ならPC-UNIXならと一縷の望みをかけあっち方面に手を出ししまいにゃプログラマにまでなってしまった事でその後の人生の貴重な時間を大いに無駄にしたし、やっぱタイミングと初期投資にかける金に失敗した人生であったなと。