Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modify time scheduling #3

Merged
merged 5 commits into from
Jul 27, 2016
Merged

Conversation

akinomyoga
Copy link
Collaborator

@akinomyoga akinomyoga commented Jul 26, 2016

@saitoha 様、さきの pull request #2 の merge ありがとうございます。

開発が停止しているのかと思って、seq2gif をてもとで勝手に変更して使わせていただいていたのですが、これを機に項目毎に pull request させていただこうかと考えているのですが構わないでしょうか。

問題点

この pull request は「_短期間に flush を繰り返すようなコマンド_の出力から animated GIF を生成してブラウザで表示すると、とてつもなくアニメーション速度が遅くなってしまう」という現象に対するものです。例として以下を御覧下さい。

ttyrec -e 'for i in {1..10000}; do printf "\r%s" $i; done; echo' loop
./seq2gif-master -w 10 -h 2 < loop > loop-master.gif
./seq2gif-play-speed -w 10 -h 2 < loop > loop-play-speed.gif

1 行目のコマンドは一瞬で完了しますが、その間に loop (ttyrecord ファイル) に大量のエントリを追加します。これを元に生成した animated GIFs を以下に添付します。
修正前 (seq2gif-master) loop-master / 修正後 (seq2gif-play-speed) loop-play-speed

実際の実行は一瞬であるにもかかわらず "修正前" の animated GIF は再生がとても遅くなっています。期待する動作は、"修正後" の animated GIF のようなものです。ここに載せた例は作為的なものですが、実際の利用でこのことが問題になったのでここで報告させて頂きます。

原因

原因は Chrome を初めとするすべてのブラウザで 0.02 sec よりも小さなフレームの遅延時間 (delay) を認識しないこと、および、認識できない場合の動作が原因です。(参考記事: Nullsleep | Jeremiah Johnson - Animated GIF Minimum Frame Delay Browser Compatibility Study 2012年の記事ですが今でも状況は変わっていません。)

この delay の下限は、特に Internet Explorer や Safari では 0.06 s と大きな値になっています。さらに、ソフトウェアによっては下限が 0.10 sec のものもあるようです (Windows フォトビューワーなど)。また、認識できるよりも小さな delay を指定した場合、どのソフトウェアもフレームの delay は "0.10s" と長めに解釈するようです。このとき何が起こるかというと、例えば、0.01 sec のフレーム 100 枚で 1 秒間のアニメーションを作成してブラウザで表示させると 10 秒間かけてゆっくりと表示されることになります。

また、ttyrec は 0.01 sec よりも小さな時間間隔の更新に対応していますが、animated GIF ではこれらを表示できません。無闇にフレームを全出力しても、良ければファイルサイズが大きくなるだけ、悪いと delay 0 のフレームが delay 0.10 sec と解釈されて間延びした再生になります。

解決法

これを解決するために 最小の delay を設定して、それより短い期間に起こる端末の状態変化は animated GIF に出力しないようにします。最小の delay を指定するためにオプションを追加しました。

  • オプション --render-interval=NUMBER

このオプションでは最小のフレームの表示時間 (整数、単位: ミリ秒) を指定します。

既定値は 20 msec にしました。現状で、Web ページに載せるために animated gif を生成する場合、フレーム表示時間を 0.02 sec より小さくすることは意味がないとの考えです。また、ブラウザ以外のソフトウェアを考えるとしても、実際のディスプレイのリフレッシュレートで 60 Hz が一般的なので、やはり 0.02 sec が妥当なところなのではないかと考えています。

また、従来の動作はこの値を 0 に指定することで再現します。

他、従来の動作は 「目にも止まらぬ速さの更新を遅くして端末の表示がどう変化していったかを可視化する」 という効用もあったのかもしれないと思います。そういった目的のためにより自然な解決法として、一緒に再生速度のオプションも pull request に含めます。

  • オプション -s FACTOR, --play-speed=FACTOR

-s 0.5 とすると 2 倍遅く再生します。-s 2 とすると 2 倍速く再生します。オプション名 -s は、ttyrec に附属の ttyplay を真似ました。このオプションは、端末の操作方法を説明するなどの目的で早回しする目的でも便利です。

確認事項

実は修正前の seq2gif でもこの問題を回避する方法があるなどということでしたらすみません。

また、show_help() で表示されるオプションの並び順がよく分かりませんでしたので、新規オプションの説明は末尾に追記させて頂きました。ご要望があれば適切な位置に挿入し直します。

その他、気になる点・アドバイスなどあればお知らせ下さい。名前付けセンスが拙いので、オプションの名称や変数名についても案があればお願いします。

よろしくおねがいいたします。

@coveralls
Copy link

coveralls commented Jul 26, 2016

Coverage Status

Coverage increased (+0.1%) to 52.076% when pulling 8bcf169 on akinomyoga:add-option-play-speed into d06c7bf on saitoha:master.

@coveralls
Copy link

coveralls commented Jul 27, 2016

Coverage Status

Coverage increased (+0.1%) to 52.076% when pulling 19f4d5a on akinomyoga:add-option-play-speed into 166125a on saitoha:master.

[問題]

(短期間に flush を繰り返す様な ttyrecord から GIF を生成して) ブラウザで表示すると、とてつもなくアニメーション速度が遅くなる。
これは Chrome を初めとするすべてのブラウザで 0.02s よりも小さなフレームの遅延時間 (delay) を認識しないことが原因である。
特に Internet Explorer や Safari では 0.06s よりも小さいと認識しない。
さらに、ソフトウェアによっては 0.10s よりも小さいと認識しないものもあるようだ (Windows フォトビューワーなど)。
認識できるよりも小さな delay を指定した場合、どのソフトウェアもフレームの delay は "0.10s" と長めに解釈する。
例えば、0.01s のフレーム 100 枚で 1 秒間のアニメーションを作成してブラウザで表示させると 10 秒間かけてゆっくりと表示されることになる。

また、ttyrec は 0.01s よりも小さな時間間隔の更新に対応しているが、animated GIF では表示できないので出力してもファイルサイズが大きくなるだけである。

[解決]

これを解決するには最小の delay を指定して、それより短い期間に起こる端末の状態変化は animated GIF 出力しないようにする。

[解決 (機能追加)]

* オプション --render-interval=NUMBER

最小のフレームの表示時間 (単位: ミリ秒) を指定する。
最後に出力したフレームから (NUMBER * 0.001) sec 経過するまでは新しいフレームは出力しない。
現状、Web ページに載せるために animated gif を生成する場合、フレーム表示時間を
0.02s より小さくすることは意味がないと思われるので既定値を 20 にする。

この値を 0 に指定すると従来の動作を再現する。

* オプション -s, --play-speed=FACTOR

再生時間の倍率を指定する。
例えば FACTOR を 2.0 にすると2倍速再生で、0.5 にすると半分の速さのスロー再生になる。
ターミナルの操作を animated GIF にする場合、早回しにしたいなどの需要がある為に追加。

短形式オプション名 -s は ttyrec に附属の ttyplay に倣った。
@coveralls
Copy link

coveralls commented Jul 27, 2016

Coverage Status

Coverage increased (+0.1%) to 52.076% when pulling c007962 on akinomyoga:add-option-play-speed into 166125a on saitoha:master.

@akinomyoga
Copy link
Collaborator Author

akinomyoga commented Jul 27, 2016

rebase (+ その他修正) しました。

seq2gif_optflag_render_interval = 0x1001,
seq2gif_optflag_play_speed = 's',
};

Copy link
Owner

@saitoha saitoha Jul 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

私のさわった限りだと、Interix(SUA/SFU)環境はlong optionが使えないようでしたので、
常に1文字のオプションを割り当てるようにしてもらった方がいいです。

この場合だと、「-i」がいいですかね。

「-i」はすでに使われているので、「-r」あたりでしょうか。

あ、すみません、「-r」も使われてましたね。大文字の「-I」でいきますか。

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。

なるほど、確かに long option の使えない環境でも同じ機能を提供するためには、一文字のオプションを割り当てた方が良いですね。勝手なオプションを追加することに対して引け目があったので long option だけにしてしまいました。修正します。

@saitoha
Copy link
Owner

saitoha commented Jul 27, 2016

@akinomyoga pull requestありがとうございます。よろしくお願いします。

確認事項について

実は修正前の seq2gif でもこの問題を回避する方法があるなどということでしたらすみません。

いままでなかったです。

show_help() で表示されるオプションの並び順がよく分かりませんでしたので、

特に決めていませんでした。後ろに追加する形でいいと思います。

@coveralls
Copy link

coveralls commented Jul 27, 2016

Coverage Status

Coverage increased (+0.1%) to 52.076% when pulling 70cf8d4 on akinomyoga:add-option-play-speed into 166125a on saitoha:master.

@coveralls
Copy link

coveralls commented Jul 27, 2016

Coverage Status

Coverage increased (+0.1%) to 52.076% when pulling d66df1e on akinomyoga:add-option-play-speed into 166125a on saitoha:master.

@coveralls
Copy link

coveralls commented Jul 27, 2016

Coverage Status

Coverage increased (+0.1%) to 52.076% when pulling d66df1e on akinomyoga:add-option-play-speed into 166125a on saitoha:master.

@akinomyoga
Copy link
Collaborator Author

修正しました。Commits x 3 ご確認頂ければと思います。

@saitoha
Copy link
Owner

saitoha commented Jul 27, 2016

@akinomyoga なるほど、大量にcatした時などの挙動が変わり、改善されました。

-s オプションの方ですが、

「目にも止まらぬ速さの更新を遅くして端末の表示がどう変化していったかを可視化する」

という目的に照らすと、-Iオプションで得られたDELAYに対して、-sオプションのFACTORを掛けて調整すべきではないでしょうか。たとえば、

ttyseq -s 0.5

とした場合、時間を2倍に引き伸ばしているので、フレーム分解能も上がったような見せ方をするのが自然であるように思えます。
この場合、デフォルトのフレーム分解能20msecに対して0.5を掛けて、10msecにしてあげればいいかな、と思っていますが、いかがでしょうか?

@akinomyoga
Copy link
Collaborator Author

akinomyoga commented Jul 27, 2016

@saitoha ありがとうございます。

少々混乱しています。こちらで勘違いしているかも知れませんが、

時間を2倍に引き伸ばしているので、フレーム分解能も上がったような見せ方をするのが自然であるように思えます。

例えば "-s 0.5" にすると結果としてフレーム数が (約) 2 倍になるというようなことを想定しているのですよね。現状の実装でそのようになっているつもりでした。

デフォルトのフレーム分解能20msecに対して0.5を掛けて、10msecにしてあげればいいかな

-s, --play-speed が絡むと時間単位が "入力の時間単位" と "出力の時間単位" の二種類あってややこしいですが、上記コメントは「フレームを入力時間でみたときに、分解能 20 msec で切り出すのではなく、分解能 20 msec × 0.5 = 10 msec で切り出す」ということを指しているのでしょうか。現在の実装では、一旦 delay = (now - prev) / gif_unit_time; を通して delay を出力時間単位に直しています。つまり delay < gif_render_interval などのフレームの出力タイミングは全て出力時間単位で判断しています。

@akinomyoga
Copy link
Collaborator Author

追記: 入力時間単位→出力時間単位は gif_unit_time で割ることによって行っています。と、ここで気付いたのですが

gif_unit_time = (int)(10000 * settings.play_speed);

ここは int ではなくて uint32_t にキャストするべきですね。すみません、直します。

@coveralls
Copy link

coveralls commented Jul 27, 2016

Coverage Status

Coverage increased (+0.1%) to 52.076% when pulling acc3098 on akinomyoga:add-option-play-speed into 166125a on saitoha:master.

@saitoha
Copy link
Owner

saitoha commented Jul 27, 2016

@akinomyoga すみません、勘違いです。確かに-s0.5にすると出力フレームが増えますね。ファイルをcatするなどという操作はしょせん一瞬で終わってしまうので、時間が2倍になっても見分けが付かずにいました。
動作確認ができたので、ここでマージさせて頂きます。

@saitoha saitoha merged commit 0ac0fd6 into saitoha:master Jul 27, 2016
@akinomyoga akinomyoga deleted the add-option-play-speed branch July 28, 2016 09:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants