khurata’s blog

khurata’s blog

モバイルオーダーとキャッシュレス

 老母が TV CM で見たビーフシチューパイを食べたいと言うので、買い物がてら、午後1時過ぎにイオン東雲のマクドナルドに行ったのだが、散々な目に遭った……という話。

 

 ここのマクドナルドを利用するのはだいぶ久方振りで、初めて見るキャッシュレスオーダー専用のタッチパネル機が3台設置してあった。 しかしうち1台は電源が入っておらず利用不可。 思い起こせば、ここで暗雲は立ちこめ始めていたのかも知れない。

 手持ちの WAON カードには、わずか数百ワオンしか入っていなかったが、紐付けしてあるイオン銀行の口座には2万6千円ほど入れてあったし、オートチャージは2万5千円に設定してある。 イオンやマルエツなど、WAON が使える店舗では、これで困った事は無かった。

 ところが、マクドナルドのキャッシュレス機は、オートチャージしてくれなかった。 これは、マクドナルドだけがそうなのか、あるいは他のキャッシュレス機(ソフトドリンクの自販機などもその類いだ)もそうなのか、私は知らないのだが、このせいで、いったんオーダーをキャンセルして、WAON ステーションでわざわざ銀行口座から手動チャージする羽目になった。 オートチャージはポイントが稼げる利点があるのだが、イオンの建物内でそれが出来ないとは思ってもいなかった。

 

 まぁこれくらいは序の口だし、目くじら立てるほどの事ではない。 問題はここからである。

 キャッシュレス機がオーダー番号を印字したレシートを吐き出してくれるので、後はマクドナルドの窓口の前で番号が呼ばれるのを待てば良い。

 しかし、どういうわけか、窓口の前にはおおよそ30人ほどが所在なさげにたむろし、窓口の卓にはざっと20人分ほどの受け取り待ち品が置いてある。 ちょっと異様な風景である。 なんだこれは……。

 窓口の様子を見ると、上方には番号の状況を知らせるディスプレイが2台あり、1台はモバイルオーダーの番号を、もう1台はキャッシュレス機の割り当てた番号を表示しているように見えた。

 ディスプレイには「待ち」と「呼び出し」の欄があり、自分の番号も確かに「待ち」の方に表示されていた。 

 

 つまり、この人達は、自分の番号が呼ばれるのを待っており、この品物達は、誰にも引き取られずに、ただ冷めるにまかせているのである。

 以前来た時は、有人レジが3つほどあったような気がするのだが(記憶はさだかでない)、今や有人レジは現金専用の1台のみで、そこは誰も並んでいない。 世はまさにモバイルでありキャッシュレスなのだから。

 

 ……15分ほど立ったまま待ち続けたが、なかなか自分の番号が「待ち」から「呼び出し」にならない。 他の人達も、ひたすらじっと待っている。 卓の上の品物は増え続ける。 店の前で待つ客はひたすら待たされる一方、決済を終えた客は受け取りになかなか現れない。

 モバイルオーダーとキャッシュレス決済が、品物の回転と、客の回転を悪化させているように見えた。 どちらも、客に番号を割り振って、その番号を待ち客に対して呼びかけなければならない仕組みだが、まるで機能していない。 現金決済の有人レジだけだった頃は、いくらなんでも15分待つなんて事は無かった。 店舗内の店員はざっと見たところ7~8人ほどはいて、人手不足とも思えない。

 「40分待ったよ」と捨て台詞を残して品物を受け取る客もいたし、「自分はウーバー配達員だから別に良いけど、お客さんはどう思うかね」と店員に聞こえよがしに言う客もいた。 こんな会話がマクドナルドで交わされるとは驚きである。

 今まで、いくつものマクドナルド店舗を利用してきたが、こんなに待たされたことはなかった。 一時は「60秒で」とか言ってなかったか。 まったくファスト・フードではない。 こんなに待つなら、ベンチを設置しておいてほしいくらいだ。

 

 若い女性客が、知り合いとおぼしき他の女性客に促されて自分の番号に気付き、あわてて受け取りに行く姿もあった。 おそらく、待ちくたびれてスマホを見ていたために、店員の呼びかけに気付けなかったのだろう。

(素人考えだが、モバイルオーダーは、アプリ内でスマホの着信音を鳴らせば、わざわざ店員が番号を呼ぶ必要も無いし気付かれない心配も無いはずで、おおいに改善の余地があると思われた)

 

 すると、ディスプレイから自分の番号が消えた。 「呼び出し」欄にも表示されない。 これはいったいどういう状態なのか……忙しそうな店員さんには申し訳無いが、その旨を訊くと、「いま順番に作っていますのでお待ち下さい」との説明。

 と言うことは、あのディスプレイには然程の意味は無い、ということなのか。

 しばらくすると別の男性客が、私と同じ現象に遭遇したらしく、店員に向かって「自分の番号が表示されなくなったんだけど」と質問していた。 察するに、この番号状態表示のシステムもまた、機能していないのである。 もしかすると、店員さん達は混乱の中で、システムに頼らずに仕事をこなそうとしているのではなかろうか……とも思える一幕だった。

 

 30分ほど待って、ようやく自分の番号が呼ばれた。 トレーを取って老母の待つ座席に戻ると、コーラとアイスコーヒーがそれぞれ1つずつなのに、ストローが1本しかない。 注文したサラダ本体は有るが、別注のドレッシングも無いしフォークも無い。 コーヒー用のガムシロップとフレッシュはちゃんと付いてきているのに、なんともちぐはぐな事である。

 おまけに、30分近くも待たされてようやく出てきた品物であるにもかかわらず、ハンバーガーもポテトもえびフィレオも、ことごとくぬるく冷めている。 出来上がってから、少なくとも10分くらい、置きっ放しだった感じである。

 

 不幸中の幸いと言えるのは、トレーを受け取った時、老母のお目当てだったビーフシチューパイはまだ出来ておらず、後から出来たての品物を口にできた事である。

 しかしこれも「幸い」と言えば言えるかもしれないが、30分待って出てきた品物が10分放置されたもので、しかもビーフシチューパイはさらに待たされたのだから、イオン東雲マクドナルドのオーダーシステムは崩壊していると言われても致し方有るまい。

 

 食事を終えると、午後2時を回っていた。 マクドナルドで食事だけするのに1時間も掛かったのだ。

 帰り際に店舗の窓口を見ると、受け取り待ちの品物は1つしか無く、待ち客も1人しかいなかった。 つまり、あの惨状は、午後0時から1時台にかけて発生していたのであろう。

 なかなか取りに現れない客達が、その後どうしたかは分からない。 無事、冷め切った品物を手にしたのだろうか。 それとも店側が受け取り手のない品物を廃棄したのだろうか。 私には知る由もない。

 平日の金曜日でさえこうなのでは、土日などは、いかばかりであろうか……客も大変だが、その大変な客を見ながら、崩壊したシステムで働かなければならない店員さん達も哀れである。

 

 素人目に一度見ただけだが、諸悪の根源は「モバイルオーダーで決済したが取りに来ない客」だと思われる。 他にもいろいろと改善すべき点は有るが、これが最大の問題に見えた。

 せめて繁忙時だけでも、モバイルオーダーを取りやめて有人レジに切り替えるとか、先ほど述べたようなアプリ改善をするとか、あるいは番号での紐付けをやめて他の仕組みを考える……など、何かしら大きな改善が必要だと強く思った午後であった。

 

(2023/12/16 追記)

 この惨状をマクドナルドのメール受付窓口に送ってみた。 返信は要らないが、何らかの改善が施されると良いなぁと思う。

NONCLIENTMETRICS 構造体などの話

1.はじめに

 Windows 10 はウインドウの枠線の太さが細すぎて掴みにくいし、似たウインドウをたくさん開くと(たとえばメモ帳やコマンドプロンプトPowerShell など)、その境界が非常に分かりづらい。 しかも Windows 10 にはウインドウ枠の太さだけを変える設定 UI が用意されていない。

 ウインドウ枠の太さを変えるネット記事は検索でたくさん出てくるが、はっきり言って、2020年頃より前の記事の内容は、現在では全く役に立たない。

 かと言って Aero Lite に書き換えるワザは、確かにウインドウ枠が太くはなるが、タイトルバーやウインドウ右上の -□× 部分も大きくなってしまい、好みではない。

 そこでメトリクス値を取得して、必要なところだけを書き換える theme ファイルを作ってみようと思ったのだが、色々な事が有ったので記録の意味で書き残しておく。

 

2.MinGWgcc は使えなかった

 まずは、現在メトリクス取得のために、次のような C プログラムを書いてみた。

ShowNonclientMetrics.c

#include <stdio.h>
#include <winuser.h>
/* https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-systemparametersinfoa */
#define SPI_GETNONCLIENTMETRICS 0x0029

/* https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmetrics */
#define SM_CXBORDER 5
#define SM_CYBORDER 6

void getDecsFromMem( int *, size_t const, unsigned char const * );
void printDecs( int const * );
void filePrintDecs( int const * );
int copyDecs( int *, int, int const * );

int main( void ) {
    NONCLIENTMETRICSA nonclient_metrics = {};
    UINT  uiAction = SPI_GETNONCLIENTMETRICS;
    UINT  uiParam = sizeof( nonclient_metrics );
    PVOID pvParam = &nonclient_metrics;
    UINT  fWinIni = 0;
    int decs[ 1000 ] = {};
    int all_decs[ 1000 ] = {};
    int copy_start_pos = 0;

    int result;

    nonclient_metrics.cbSize = sizeof( nonclient_metrics );
    if ( SystemParametersInfoA( uiAction, uiParam, pvParam, fWinIni ) ) {
        printf( "SystemParametersInfoA() succeeded." );
        printf( "\n  .cbSize (UINT) =              %d /\t 0x%08x /\t", nonclient_metrics.cbSize, nonclient_metrics.cbSize );
        getDecsFromMem( decs, sizeof( UINT ), ( unsigned char * )&( nonclient_metrics.cbSize ) );
        printDecs( decs );
        copy_start_pos = copyDecs( all_decs, copy_start_pos, decs );
        printf( "\n  .iBorderWidth (int) =         %d /\t 0x%08x /\t", nonclient_metrics.iBorderWidth, nonclient_metrics.iBorderWidth );
        getDecsFromMem( decs, sizeof( int ), ( unsigned char * )&( nonclient_metrics.iBorderWidth ) );
        printDecs( decs );
        copy_start_pos = copyDecs( all_decs, copy_start_pos, decs );
        printf( "\n  .iScrollWidth (int) =         %d /\t 0x%08x /\t", nonclient_metrics.iScrollWidth, nonclient_metrics.iScrollWidth );
        getDecsFromMem( decs, sizeof( int ), ( unsigned char * )&( nonclient_metrics.iScrollWidth ) );
        printDecs( decs );
        copy_start_pos = copyDecs( all_decs, copy_start_pos, decs );
        printf( "\n  .iScrollHeight (int) =        %d /\t 0x%08x /\t", nonclient_metrics.iScrollHeight, nonclient_metrics.iScrollHeight );
        getDecsFromMem( decs, sizeof( int ), ( unsigned char * )&( nonclient_metrics.iScrollHeight ) );
        printDecs( decs );
        copy_start_pos = copyDecs( all_decs, copy_start_pos, decs );
        printf( "\n  .iCaptionWidth (int) =        %d /\t 0x%08x /\t", nonclient_metrics.iCaptionWidth, nonclient_metrics.iCaptionWidth );
        getDecsFromMem( decs, sizeof( int ), ( unsigned char * )&( nonclient_metrics.iCaptionWidth ) );
        printDecs( decs );
        copy_start_pos = copyDecs( all_decs, copy_start_pos, decs );
        printf( "\n  .iCaptionHeight (int) =       %d /\t 0x%08x /\t", nonclient_metrics.iCaptionHeight, nonclient_metrics.iCaptionHeight );
        getDecsFromMem( decs, sizeof( int ), ( unsigned char * )&( nonclient_metrics.iCaptionHeight ) );
        printDecs( decs );
        copy_start_pos = copyDecs( all_decs, copy_start_pos, decs );
        printf( "\n  .lfCaptionFont (LOGFONTA) =   %d /\t 0x%08x /\t", nonclient_metrics.lfCaptionFont, nonclient_metrics.lfCaptionFont );
        getDecsFromMem( decs, sizeof( LOGFONTA ), ( unsigned char * )&( nonclient_metrics.lfCaptionFont ) );
        printDecs( decs );
        copy_start_pos = copyDecs( all_decs, copy_start_pos, decs );
        printf( "\n  .iSmCaptionWidth (int) =      %d /\t 0x%08x /\t", nonclient_metrics.iSmCaptionWidth, nonclient_metrics.iSmCaptionWidth );
        getDecsFromMem( decs, sizeof( int ), ( unsigned char * )&( nonclient_metrics.iSmCaptionWidth ) );
        printDecs( decs );
        copy_start_pos = copyDecs( all_decs, copy_start_pos, decs );
        printf( "\n  .iSmCaptionHeight (int) =     %d /\t 0x%08x /\t", nonclient_metrics.iSmCaptionHeight, nonclient_metrics.iSmCaptionHeight );
        getDecsFromMem( decs, sizeof( int ), ( unsigned char * )&( nonclient_metrics.iSmCaptionHeight ) );
        printDecs( decs );
        copy_start_pos = copyDecs( all_decs, copy_start_pos, decs );
        printf( "\n  .lfSmCaptionFont (LOGFONTA) = %d /\t 0x%08x /\t", nonclient_metrics.lfSmCaptionFont, nonclient_metrics.lfSmCaptionFont );
        getDecsFromMem( decs, sizeof( LOGFONTA ), ( unsigned char * )&( nonclient_metrics.lfSmCaptionFont ) );
        printDecs( decs );
        copy_start_pos = copyDecs( all_decs, copy_start_pos, decs );
        printf( "\n  .iMenuWidth (int) =           %d /\t 0x%08x /\t", nonclient_metrics.iMenuWidth, nonclient_metrics.iMenuWidth );
        getDecsFromMem( decs, sizeof( int ), ( unsigned char * )&( nonclient_metrics.iMenuWidth ) );
        printDecs( decs );
        copy_start_pos = copyDecs( all_decs, copy_start_pos, decs );
        printf( "\n  .iMenuHeight (int) =          %d /\t 0x%08x /\t", nonclient_metrics.iMenuHeight, nonclient_metrics.iMenuHeight );
        getDecsFromMem( decs, sizeof( int ), ( unsigned char * )&( nonclient_metrics.iMenuHeight ) );
        printDecs( decs );
        copy_start_pos = copyDecs( all_decs, copy_start_pos, decs );
        printf( "\n  .lfMenuFont (LOGFONTA) =      %d /\t 0x%08x /\t", nonclient_metrics.lfMenuFont, nonclient_metrics.lfMenuFont );
        getDecsFromMem( decs, sizeof( LOGFONTA ), ( unsigned char * )&( nonclient_metrics.lfMenuFont ) );
        printDecs( decs );
        copy_start_pos = copyDecs( all_decs, copy_start_pos, decs );
        printf( "\n  .lfStatusFont (LOGFONTA) =    %d /\t 0x%08x /\t", nonclient_metrics.lfStatusFont, nonclient_metrics.lfStatusFont );
        getDecsFromMem( decs, sizeof( LOGFONTA ), ( unsigned char * )&( nonclient_metrics.lfStatusFont ) );
        printDecs( decs );
        copy_start_pos = copyDecs( all_decs, copy_start_pos, decs );
        printf( "\n  .lfMessageFont (LOGFONTA) =   %d /\t 0x%08x /\t", nonclient_metrics.lfMessageFont, nonclient_metrics.lfMessageFont );
        getDecsFromMem( decs, sizeof( LOGFONTA ), ( unsigned char * )&( nonclient_metrics.lfMessageFont ) );
        printDecs( decs );
        copy_start_pos = copyDecs( all_decs, copy_start_pos, decs );
        printf( "\n  .iPaddedBorderWidth (int) =   %d /\t 0x%08x /\t", nonclient_metrics.iPaddedBorderWidth, nonclient_metrics.iPaddedBorderWidth );
        getDecsFromMem( decs, sizeof( int ), ( unsigned char * )&( nonclient_metrics.iPaddedBorderWidth ) );
        printDecs( decs );
        copy_start_pos = copyDecs( all_decs, copy_start_pos, decs );
        printf( "\nAll decimals =\n" );
        printDecs( all_decs );
        filePrintDecs( all_decs );
        printf( "\n" );
    }
    else {
        puts( "SystemParametersInfoA() failed." );
    }

    printf( "\n" );
    if ( result = GetSystemMetrics( SM_CXBORDER ) ) {
        printf( "GetSystemMetrics() succeeded." );
        printf( "\n  .SM_CXBORDER (int) =         %d /\t 0x%08x\n", result, result );
    }
    else {
        puts( "GetSystemMetrics() failed." );
    }

    printf( "\n" );
    if ( result = GetSystemMetrics( SM_CYBORDER ) ) {
        printf( "GetSystemMetrics() succeeded." );
        printf( "\n  .SM_CYBORDER (int) =         %d /\t 0x%08x\n", result, result );
    }
    else {
        puts( "GetSystemMetrics() failed." );
    }

    return 0;
}

void getDecsFromMem( int * o, size_t const sz, unsigned char const * s ) {
    size_t i;

    for ( i = 0; i < sz; i += 1 ) {
        *o = ( int )( *( s + i ) );
        o ++;
    }
    *o = -1; /* set sentinel */
}

void printDecs( int const * s ) {
    while ( *s >= 0 ) {  /* while sentinel */
        printf( "%d ", *s );
        s ++;
    }
}

void filePrintDecs( int const * s ) {
    FILE * f;

    if ( NULL != ( f = fopen( ".\\ShowNonclientMetrics.txt", "w" ) ) ) {
        while ( *s >= 0 ) {  /* while sentinel */
            fprintf( f, "%d ", *s );
            s ++;
        }
        fclose( f );
    }
}

int copyDecs( int * o, int pos, int const * s ) {
    while ( *s >= 0 ) {  /* while sentinel */
        o[ pos ] = *s;
        s ++;
        pos ++;
    }
    o[ pos ] = -1; /* set sentinel */
    return pos;
}

 ウチは WindowsC/C++ プログラムを書く際の第1選択が MinGWgcc なので、何の疑いも無くこれを書いたわけだが(厳しく見れば printf( ) の引数が型不一致だし、無駄な繰り返しもあるが、現在値を取得するという目的のためだけに書いたので大目に見てほしい)、iPaddedBorderWidth が無いというコンパイルエラーになってしまう。

 そう言われても、 https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-nonclientmetricsa によれば iPaddedBorderWidth は有る。

 これはもしやウチの gcc が古いバージョンなのかと思い、MinGW Installer を起動してみたところ、はたして最新でない gcc コンポーネントがいくつかある。 さっそくアップデートして、再びコンパイルするも、やはり iPaddedBorderWidth が無いとエラーを吐かれる。

 仕方無く MinGW インストールフォルダー直下の include/winuser.h を直接見てみると……確かに無い、iPaddedBorderWidth が。

 つまりこの件に関して、MinGWgcc は使えない、という事である。

 

3.Visual Studio 2019 は使えた

 やむなく VS2019 を起動して空のプロジェクトを作り、先ほどのソースを取り込んでコンパイルエラーを取り除いた、次のような C プログラムをでっち上げた。

ShowNonclientMetrics.c (VS2019 版)

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <windows.h>
/* #include <winuser.h> */
/* https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-systemparametersinfoa */
#define SPI_GETNONCLIENTMETRICS 0x0029

/* https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmetrics */
#define SM_CXBORDER 5
#define SM_CYBORDER 6

void getDecsFromMem( int *, size_t const, unsigned char const * );
void printDecs( int const * );
void filePrintDecs( int const * );
int copyDecs( int *, int, int const * );

int main( void ) {
    NONCLIENTMETRICSA nonclient_metrics = { 0 };
    UINT  uiAction = SPI_GETNONCLIENTMETRICS;
    UINT  uiParam = sizeof( nonclient_metrics );
    PVOID pvParam = &nonclient_metrics;
    UINT  fWinIni = 0;
    int decs[ 1000 ] = { 0 };
    int all_decs[ 1000 ] = { 0 };
    int copy_start_pos = 0;

(以下同じ)

 これは警告が出るものの、期待通りに動作した。 やはり餅は餅屋で、Windows プログラムは Microsoft に限る、という事か。 VS2019 は何をするにもいちいち重くて、あまり好きではないのだが、今回ばかりは致し方ない。

 

4.NONCLIENTMETRICS の大きさは

 あとは上記プログラムが吐き出してくれた数字列を、theme ファイルの [Metrics] セクションの NonclientMetrics に書き込んで、ウインドウ枠の太さだけ書き換えれば良いであろう(参考 https://learn.microsoft.com/ja-jp/windows/win32/controls/themesfileformat-overview )。

 ……いや待て。 上記リンクで掲載されている NonclientMetrics には、数字が 340個しか書かれていないが、プログラムが吐き出した数字列は 344個あるではないか。

 もしかすると、MinGW と上記リンク記事は、双方とも iPaddedBorderWidth なんてものは無いという認識なのだろうか。

 

5.とにかく実行だ、Windows が壊れるわけではあるまい

 とにかく 344個のメトリクス値は得られたので、まずは先頭の 340個を theme ファイルに書き込んで実行してみる。 当然、iPaddedBorderWidth 部分が無いのだから、ウインドウ枠は変わらない。

 そこで次は 344個の数値を書き込んで試してみるが、なぜかウインドウ枠の太さは変わらない。 iPaddedBorderWidth 部分の、元の値は 4000 だったが、ヤケクソで 60000 とかに書き換えても変わってくれない。

 もしかすると iPaddedBorderWidth の読み取りを有効にするには、レジストリをいじらなければならないのか……などと思いつつ、値をいろいろ変えて試していると、なんとウインドウ枠の色が変わってしまった。 これじゃ話が違うではないか。

 

6.レジストリの書き換えはどうか

 ネット記事を見ていると、HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetricsPaddedBorderWidth を書き換えれば出来る、としているものが見られる。

 早速 regedit で見てみると、元々の値は -60 となっている。

 何かの記事で、これは -15 を1単位としていて、-60 は「4」を表す、というのを読んだ記憶があるので、0 にしたり -120 にしてみたり、いろいろ変えて再起動を繰り返してみたが……何も変わらない。

 

7.おわりに

 結局のところ、すべては徒労であった、という事か。

 それにつけても、デスクトップアイコンの「一覧」「詳細」を出来なくしたり、Microsoft の「昔ながらの UI デザインを制限しよう」という意図は、よく分からない……。

HandBrake の PAR まわりについて

 ウチでは HandBrakeCLI の簡易的な GUI ラッパーを HTAJScript で自作して MP4 動画をエンコードしているのだが、先日、HandBrake を 1.3.3 から 1.6.1 にアップデートしたところ、生成される動画のピクセルサイズがおかしくなってしまった。

 

 よくある 1440x1080 のソースをエンコードしたら 1624x1080 という変なピクセルサイズの MP4 動画が生成されてしまうし、1920x1080 をエンコードしても 1624x1080 になってしまう。

 

 いくらなんでもこれはおかしいので調べてみたら、どうやら HandBrake の PAR 処理が 1.4.x から変更されたらしい。

 

 横 1920 で再生したい動画の場合、ストレージ幅を -w 1920 もしくは -w 1440 に指定し、さらに --custom-anamorphic を指定して --display-width を常に 1920 にしていたが、1.4.x 以降はこれではダメなのだ。

 少し調べてみて、通常使われているようなピクセルサイズであれば、--pixel-aspect を指定すれば良いことが分かった。

 

 以下は、よく使われる映像サイズにおけるストレージサイズとディプレイサイズと PAR の対応表である。

映像 ストレージサイズ (SAR) ディスプレイサイズ (DAR) PAR
FHD 1920x1080 (16:9) 1920x1080 (16:9) 1:1
HD 1440x1080 (4:3) 1920x1080 (16:9) 4:3
HD 1280x 720 (16:9) 1280x 720 (16:9) 1:1
SD 720x 480 (3:2) 640x 480 (4:3) 8:9
SDwide 720x 480 (3:2) 853x 480 (16:9) 32:27

 この PAR 値を --pixel-aspect で指定し、--custom-anamorphic をやめて --auto-anamorphic に変え、--display-width を削除する。

 こうすると、HandBrake は PAR からアナモルフィックを自動計算して、正しいストレージサイズ・ディスプレイサイズの MP4 を生成してくれる。

 

 たとえば SD ソースのワイド画面をエンコードしたい場合は、

HandBrakeCLI.exe -i "元ファイル.mpg" -o "生成ファイル.mp4" -Z "Fast 480p30" -f mp4 -e x264  -q 23 -r 29.970 --cfr -w 720 -l 480 --crop 0:0:0:0 --auto-anamorphic --pixel-aspect 32:27 --modulus 8  --decomb="default" -a 1 -E ffac3 -B 192 --mixdown stereo -R 48 -x :bframes=3:min-keyint=2:keyint=30:nal-hrd=vbr:bluray-compat=1

のようにコマンド指定すればよい(肝要な部分を赤文字で示した)。

 

Twitter ショック

 イーロン・マスク氏の方針により、2023年7月初め頃からツイッターに閲覧制限がかかった。 これによって、市井からは「10分くらいで制限にかかってしまい使い物にならない」「世間の状況が分からない」「企業の情報発信がままならない」「自治体の情報発信が難しくなった」などの声が上がっている(日テレ「news zero」などより)。

 

 しかし、私みたいな「低浮上アカウント」からしてみれば、「今までさんざんタダで使い倒して何年もの間それで利益を得てきたくせに、今更何を言っているんだ」という思いである。

 上記のようなボヤキを発している方々は、今まで1度でも、ツイッターのサーバーや回線設備に課金したことがあるのか。

 まるで空気のように、あるいは自らが所有する奴隷のように、「使えて当然」な自然の権利だと思い込んで、好きなようにタダでこき使い続けてきただけではないのか。

 

 それが急に使えなくなったから文句を言うなど、ちゃんちゃら可笑しい。 もう充分だろう。 タダで拡散してもらって、タダで知名度をもらって、それで仕事をしてきたのに、ツイッターへは1円も落とさず、感謝の一言すら無く、何年も過ごしてきたのだから。

 

 インターネット・サービスを構築して運営した経験を持つ人、というのは世間一般から見ればきわめて少ないが、そういうスキルと経験を持つ人から見れば、ツイッターの閲覧制限は大いに理解できるだろう。

 世界中から無料で24時間365日いつでも無停止で投稿され閲覧され続けるネットサービスを構築し安定運営するのは、技術的にも金銭的にも並大抵のことではない。 他にも FacebookInstagram など、ワールドワイドな SNS はいろいろあるが、そのどれもが、多数の技術者の努力と、経営者の尽力によって成り立っている。

 

 特に自治体は、まるで自分達の公器であるかのようにツイッターなどの SNS をタダで使い続けてきたが、本来、自治体や国家は「自らの所有する手段」で、市民に情報公開すべきだし、そうした場合にどれほどの血税を投入しなければならないのかを試算してみれば、ツイッターから今までどれほどの搾取をし続けてきたか、骨身に沁みて分かるのではないか。

 そもそもの話、1私企業が運営する SNS に、「社会の公器」や「社会のインフラ」のような役目を負わせる事自体に無理がある。 それによって情報拡散が歪められるであろう危険性も散々指摘されてきたはずだ。

 

 「news zero」は、イーロン・マスク氏の意図を「情報は無料ではない」と解釈していた。 その解釈が正しいかどうかは私には分からないが、今まで何年もの間、あまりにも多くの人々が、ネットサービスを「有って当然だしタダで当たり前」と思い続けていたのは確かだと言ってよい。

 そんな乱暴きわまりない意識は改善されるべきだと私は思うし、若い人達が小さな子供の頃からそういう意識を持たせてきたのは大人の怠慢であった、とも思うのである。

(了)

固定マウンタ Ainex HDM-44A 使用記

 これは DELL Optiplex 3010 Desktop光学ドライブを取り外し、Ainex HDM-44A を取り付けて SATA HDD を増設した記録です。

 Optiplex 3010 の光学ドライブはツールレスで脱着できる優れモノですが、HDM-44A を PC 本体に取り付けるための付属ネジはタッピング・ビス(ネジこむことでネジ山を切っていくタイプ)なので、ここにちょっとしたコツが要ります。

 

 まずは HDM-44A が届いたところです。

photo of Ainex HDM-44A

Ainex HDM-44A

 今回は箱写真2の使い途、つまり3.5インチHDDを内蔵するために購入しました。 箱を開けてみます。

 

 

opening box of HDM-44A

HDM-44A の外箱を開けたところ

 みっちりキチキチに入っています。 箱を逆さにして振らないと取り出せません。 無駄の削減がすごいです。

 

 付属のネジで、HDD を HDM-44A の底面から、4箇所でしっかりネジ止めしました。 ここは説明不要でしょう。

 

 ちよっとしたコツが必要なのは、HDM-44A の両側面に取り付けるタッピングビスです。 Optiplex 3010 の光学ドライブに付属するネジは、ネジ山が途中までしか切られておらず、そのため目いっぱい締めても、光学ドライブとネジ頭の間に数ミリほどの隙き間が出来ます。

screw for optical drive of DELL Optiplex 3010

Optiplex 3010 光学ドライブ用ネジ

 この幅と同じ幅を目指して、タッピングビスを締め込んでいきます。 締め込みが甘いとネジ頭が邪魔して HDM-44A を装着できませんし、締めすぎると「幅」が足りずに、これまた装着できません。

 許容される高さまでタッピングビスを締め込んだら、HDD 取り付け済みの HDM-44A を、Optiplex 3010 の光学ドライブマウンターに差し入れてゆきます。

 

 うまくゆけば、このように「ツライチ」に仕上がります。

HDM-44A in Optiplex 3010 Desktop

Optiplex 3010 に HDM-44A を装着したところ

 色的にもバッチリ(死語)で、まるで DELL が用意したパーツのようです。

 

 なお、写真には撮りませんでしたが、Optiplex 3010 Desktop の光学ドライブを付け外しするには、あらかじめ本体カバーを開けた上でフロントカバーを外しておく必要があるのでご注意下さい(上部に3つあるツメを指で起こすと簡単に外せます)。

 

 あとは装着した SATA HDD に本体内の電源ケーブルSATA ケーブルを取り付けて、完成です。

 電源を入れて起動し即座に F2 キーで BIOS 画面に入り、装着した SATA HDD が認識されていることを確認してから Windows を起動します。

 マイコンピューターやエクスプローラーで、装着した HDD が認識されている事を確認して、めでたく作業終了です。

(新品 HDD の場合は、「ディスクの管理」から新規パーティションを確保する必要がある場合もあります)

(了)