初めての方はこちら

Last-modified: 2025-12-25 (木) 09:46:56

このwikiは、一般向けの解説サイトではなく
「AIに絵を描いてもらって適当に貼って適当に雑談するスレ」に出入りしている人向けです。
一般的とは言い難いエッチだったり過激な表現が数多くありますので苦手な方は見ない方がいいと思います。

※ちなみにこのwikiはプログラミングとか詳しくない人が書いてます。間違いがある可能性があります※
※また編集時の情報と最新verでは情報が異なる可能性があるよ※
みんなで編集してね

AI情報収集の際の重要な注意事項

AI技術は高速な進化を続けており、同時に技術や知識の陳腐化も激しいのが現実です。
このwikiを含めてwebにはAIに関する新しい有用な情報と、陳腐化してしまった過去の情報が入り乱れています。
(もちろん現在でも有効な過去の情報もあります。)
作成・記述された日付の確認など、情報を取捨選択する感性が必要です。

テンプレだよ

AIに絵を描いてもらって適当に貼って適当に雑談するスレ
性器描写は要修正(各種ツールで性器全体にモザイクをつけること)・絵師が滅びますぞーやAIと絵描きの問題については単純に荒らしなので黙delでお願いします

◇ 登録不要でお試し可能
https://huggingface.co/spaces/Asahina2K/animagine-xl-4.0
https://dezgo.com

◇ 人工知能板 - http://dec.2chan.net/85/futaba.php?mode=cat

◇ としあきdiffusion Wiki - https://wikiwiki.jp/sd_toshiaki/
◇ 最近のできごと - https://wikiwiki.jp/sd_toshiaki/-s/18780c25
◇ AI絵導入ガイド - https://wikiwiki.jp/sd_toshiaki/-s/0dd28e00#tools_guide
体験版リンク集 - https://wikiwiki.jp/sd_toshiaki/-s/8ef2353c
◇ より詳しい修正基準 参考 - https://wikiwiki.jp/sd_toshiaki/-s/05ed8846#s2952694

AI絵導入ガイド

画像生成AIを利用する手段は、大きく分けて以下のものがあります。

  • 無料デモ
    WAI-IL v12.0デモAnimagine_v4デモなど。
    とにかくまず試してみたい人向け。無料でお試し生成できる。
    インストールもアカウント登録も不要。利用する端末のスペックも不問。Webブラウザから利用可能なのでインターネット接続できているPCやスマホさえあればOK。

    デモ版なので機能面ではかなり制限されているが、画像生成AIがどのようなものか知りたいならまずはここから始めてみよう。
    試してみた上でもっとやってみたい場合は下記のWebサービスやローカル環境を使ってみよう。

  • 生成AIサービス
    PixAITensor.ArtNovelAIなど。

    画像生成AIを本格的に始めてみたい人向け。
    企業が運営しているWebサービスで、生成に有料通貨が必要となる。
    一応、サービスの中には「毎日無償で少量の通貨が配布される」ものもいくつかある。

    無料デモと同様、サーバー側が画像生成を行うため、インターネット接続できているPCやスマホさえあればOK。中にはスマホアプリが用意されているスマホ特化型のサービスもある。

    後述のローカル環境と比較すると、高額のPCを用意しなくてもいいものの、ガッツリ画像生成をやろうとすると、それなりにお金がかかる。
    また、最大の悩みどころは、突然仕様変更や規約変更がなされ、エロ絡みの規制強化を受ける可能性もある。

  • クラウドGPUサービス
    ローカル環境に近いものををクラウド上で構築してしまう方法。PaaS型であれば操作はローカルとほとんど変わらない(Google ColabなどJupyter NotebookのSaaS型のものはNotebook特有の操作が必要)。
    生成AIサービスと違い、サービスの性質上操作内容をリアルタイムに把握できないため、プロンプトや生成を検閲・拒否されることはない。ただし利用規約により禁止されている行為は自己責任であり、問題のある画像や動画ファイルをクラウドドライブに保存した場合などはファイル検閲によるアカウント停止等のリスクがある。
    また、URLを第三者に共有すれば内容が把握できるため、A1111ComfyUIそのものに認証をかけるなど、生成AIサービスよりユーザーの責任範囲が大きい。
  • ローカル環境
    A1111、reForge;、ForgeForge Classic、ComfyUIなど。
    理由は人それぞれだが、最終的にこれに行き着くとしあきが多い(2024年12月のアンケートでは約9割)。
    自分のPCにツールを導入(=環境構築)し、PCに搭載しているグラボで計算処理を行う。
    デスクトップPCに、ある程度良い性能のグラボを搭載して行うのが一般的。
    環境構築にはEasy◯◯シリーズまたはStability Matrixを利用するのが手軽で、現在の主流になっている。

    一度環境を整えてしまえば、必要となるのは電気代のみといってよく、表現規制もないため、生成画像を公開せずに自分だけで楽しむ限りは自由に使えるのが強み。
    ただ、既にある程度のスペックのゲーミングPCを持っているという場合を除けば、一般的な目線でいえばかなり高額のPCを入手することが大前提となるため、初期投資の負担はかなり大きい(最低ラインですら20万クラス)。

    最終的にここに行き着くケースは多いが、端からローカル環境を構築しようとは考えずに、まずは無料デモや生成AIサービスで画像生成AIがどのようなものか体感した上でローカル環境を構築するかどうか検討したいところ。

参考:エロ画像の生成について

  • 生成AIサービスは、サービスによってエロ規制の方針が異なる。
    • 大手企業(ChatGPT、MS Bing、Google ImageFX、Grok等)はエロ全面禁止の所が多く、指示(プロンプト)の内容を自動審査した上で、生成結果の画像を自動審査するという二段構えが主流であり、それを掻い潜ってエロ画像生成をするのはかなり難しい。
    • それ以外の生成AIサービスについても、実写のエロについては厳しい傾向。
    • 二次元であってもロリエロについては結構厳しく、プロンプトの自動審査の段階で弾かれることもある。
    • PixAI、Tensor.ART、SeaArt等はスマホアプリ版も存在するが、AppleとGoogleがエロに厳しいので、スマホアプリ版ではエロ画像の生成と閲覧が禁止されており、エロ関係はPCや、スマホのブラウザ版を利用したほうが良い。
  • ローカル環境については利用するモデルによってエロの得意・不得意がある。
    • エロが不得意なモデルだと、例えば性器を指示しても股間が平らに作画されたりする。
    • 2025年11月現在はSDXL世代の、特にイラストリアス(IL)系の派生モデルを利用するのが主流で、一例を挙げると二次元ならWAI-illustrious-SDXLとか。
    • Civitaiでフィルタとソートを使ってモデルを探すのも手。評価が高いものは大抵エロにも対応している。

ローカル環境

自分のPCでグラボを使って画像生成させる方法。
生成エンジンであるStable Diffusion(SD)は共通で、SDに対して描画指示を出すユーザーインターフェース(UI)を選ぶことになる。
web配布物や自作による学習データ(LoRA等)の追加が可能で、版権キャラクターもすけべな絵も電気代だけで好きなだけ出力できる。
十分な性能のパソコンを用意できるならこれ。

  • Stable Diffusion Web UI (定番) A1111ローカル版導入
    • 開発者のアカウント名「AUTOMATIC1111」に(ちな)んでA1111 WebUIやSD WebUIと略されることもある。
    • AI絵における老舗のツールであり、知名度が高く、2025年4月現在もなかなかのシェアを誇る。
    • 出回っている情報も多く、プラグインで追加できる機能も多数ある。この2点が強み。
    • 現在は後述のStability Matrixを使うことで、昔に比べると導入が簡単になっている。
      (昔ながらの手法でインストールする場合、事前に別途「Python 3.10」「Git」のインストールが必要)
    • RADEONでもRadeon ZLUDAを使うことでwindowsでも利用が可能になった。
    • Intel GPUや、また速度は遅いがCPUでも動く → Nvidia以外のグラボに関して
    • 後述の他ソフトらと比べると、VRAM必要量が多目。
      16GB以上あれば安心だが、12GB以下ならreForgeやForgeが効果的。
    • SD3.5、Flux.1、AuraFlowなどには非対応。
    • ILやNoobのv-pred系モデルを利用したい場合、devブランチに切り替える必要がある。
    • 2024年7月のv1.10.1を最後に、大きな更新は止まっている。
      ただdevブランチではメンテと更新が一応続いており、v-predやRTX 5000番台への対応が済んでいる。
    • 2024年12月に実施されたとしあきアンケートでは使用率第2位(約30%)と、いまだ高い数字を示した。
  • Forge →Forgeの導入
    • 上記SD A1111 WebUIの内部処理を最適化したもの。UIはA1111webUIに近い。
    • 特にVRAM消費量が大幅に削減されており、VRAM6~8GBのグラボユーザーやHires. fix利用時には恩恵が非常に大きい。
    • 拡張機能はA1111webUIと互換が無い物もある。
    • 2024年1~6月においては速度と省VRAM性から高い人気を誇っていた。
    • 2024年7~8月にかけて大工事が行われたため、それ以前と以後とでは機能や内部的な作りが大きく異なる。
      2024年6月までの物は俗に「旧Forge」、7月以降の物は「新Forge」「Forge 2」などと呼ばれている。
    • 現在のForgeは、SD1.5やSDXLに加えてFLUX.1やSD3.5にも対応しているのが特長。
      一方で、Gradio 4を採用しているため、拡張機能の互換性においてデメリットになっている部分もある。
    • 2025年6月を最後に更新は止まっており、他のWebUIのようなRTX 5000番台への対応は行われていない。
      Stability Matrixを利用して導入すればStability Matrix側でRTX 5000番台への対応が行われる。
  • reForge (推奨)
    https://github.com/Panchovix/stable-diffusion-webui-reForge
    • A1111webUIの改良版であるForgeのうち、旧Forgeの方向性を引き継いで発展させた物。
    • UIはA1111webuiや旧Forgeとほぼ同じで、VRAM利用量もForge並で優秀。
    • A1111webUI同様にGradio 3を採用しているので、拡張機能の互換性に優れる。
    • Stability Matrixを利用しての導入が可能。
    • 2024年12月現在reForgeの環境を導入するならばEasyReforgeを利用するのがかなり楽。詳しくはこちら
    • ILやNoobなど、SDXL世代のモデルを主に扱うユーザーからの人気が高い。
    • FLUX、SD3.5、AuraFlow等には対応していない。
    • 2024年夏から2025年夏現在において、最も人気が高いツールである。
    • 2025年3月11日に大規模更新が行われ、バックエンドがComfyUIのアップストリームからいくつかの機能を取り入れたものになっている。それ以前のバックエンドは"old forge backend"と呼ばれて区別されており、2025年12月現在はmain-oldブランチとして残されている
  • Forge-Classic
    https://github.com/Haoming02/sd-webui-forge-classic
    • reForgeと同様に旧Forgeから派生したwebui。
    • 先進的な要素を積極的に取り入れていたreForgeに比べるとシンプル志向。
      Forge/reForgeから使用頻度が少ない機能が多く削除されており、WD14-Taggerなど動作しない拡張機能も存在する。
    • Stability Matrixを利用しての導入が可能。
    • reForge開発者のPanchovix氏も移行先の候補として挙げている。
  • ComfyUIComfyUIの導入
    • 点在する処理内容(ノード)を線で繋いで作るフローチャートにより、処理内容を視覚的に理解して描画命令を出せる。独特のUIが特徴。
    • 起動が高速で、1111よりVRAMの必要量が少ないのが大きな利点。
    • 最新技術の導入が早い傾向にあり、SD3やFlux.1、AuraFlowといったSDXLの次世代描画AIにも対応している。
    • Stability Matrixでの導入が可能。
    • ワークフローがとっつきにくく、自在に画像を出せるまでにはやや時間がかかるかも。
  • SD.Next
    https://github.com/vladmandic/sdnext
    • 元々はAutomatic1111版から派生したwebuiだったが現在は独自に発展を遂げている。
    • 先進的な要素を積極的に取り込んでいるのが特徴。
    • StableDiffusion以外にも多くのモデルが利用可能。
    • nVidia製GPU+Windows/Linuxという一般的な環境だけでなく多様なプラットフォームをサポートしている。

他にもFooocus、StableSwarmUI、NMKDなど

  • Stability Matrix (推奨)
    • 上記のA1111 WebUI、reForge、ComfyUI等、複数の画像生成AI関連ツールを一括して管理するツール。
      各種ツールを、GUIとマウス操作でお手軽に導入できる。導入後はランチャーにもなる。
    • Gitのポータブル版が同梱されているので、WindowsにGitをインストールしていなくてもOK。
    • Pythonが同梱されているので、WindowsにPythonをインストールしていなくてもOK。
    • 各ツール間でCheckpointやLoRAフォルダを共有するための機能(モデルの共有)が標準で用意されている。
    • 注意点として、Stability Matrix経由で起動する場合、「webui-user.bat」は使用されない。
      代わりに、起動オプション(--xformers等)は、各パッケージのボタンから設定する。
    • 導入方法はAI画像生成の新時代! 「Stability Matrix」で最新の画像生成を体感せよ!(窓の杜)が詳しい。
    • 手動で導入した場合とは様々な面で違いがあるのでトラブルシューティングが難しくなることには注意。
古い情報

2023年に使われていたフローなど
ツール選び(クリックで拡大できます)

  • NMKD →NMKDの導入
    • 導入がワンタッチ版並みに簡便であることと、RadeonやCPUでの画像生成にも対応しているのが特長。
      とはいえCPUでの画像生成はかなり遅いので厳しいけど…。
  • ワンタッチ版1111 →ワンタッチ版1111の導入
    • 有志(個人)がローカル版1111の導入をかなり簡単にして配布しているもの。
      ハードルをだいぶ下げてくれている。PCに不慣れな人にオススメ。
    • 導入さえしてしまえば、操作や機能における1111との差異はかなり少ない。
    • 基本的に1111の拡張機能も利用できるが、一部例外あり。

生成AIサービス

  • PixAI (無料利用可) (オススメ)  > https://pixai.art/
    • 本社はシンガポール。
    • 後述のTensor.ArtやSeaArtと類似の生成AIサービス。
      群雄割拠する戦国時代なので、Yodayo、Moescapeなど類似サイトは他にも多数ある。
    • PixAIはその中でも比較的大手。日本人ユーザーも少なくない。
      無料配布のクレジットに期限がないため翌日以降に持ち越して蓄積可能という特長がある。
    • 「クレジット」という独自通貨を消費して、画像生成や自作LoRAの学習を行える。
      無課金でも毎日クレジットを受け取り可能。月額課金するとクレジットがより多く貰えるほか、
      画像生成の待ち時間がやや短くなる(快速生成)、一度に使えるLoRAの数が増えるなどの特典がある。
    • スマホアプリではすけべ絵を生成できないが、ブラウザから利用する際はOK。
    • ふたばではAIエロスレでの利用者が多目な印象。
    • 詳細や利用方法はこちらのページを参照。体験版リンク#PixAI
  • Tensor.Art (無料利用可) > https://tensor.art/
    • 本社は中国・上海市。
    • 生成した画像ファイル内にメタデータが残る(NAI、Moescape、Dezgoも同様)。
    • こちらも通貨名は「クレジット」。クレジットを消費して画像生成やLoRAの自作が可能。
      無課金でも毎日50クレジットの付与がある。デフォルトの出力設定で62枚分に相当。
      ただしこの50クレジットは翌日に持ち越しできない。
      各種デイリータスクをこなすと、翌日以降に持ち越し可能な蓄積クレジットを最大で合計50貰える。
    • すけべ絵生成不可。
      • 25年11月にエロ不可のTensor.Artとエロ可のTensorHub.Artで区分けされたが、Hubでは無料の通貨(こちらでは「トークン」)が一切配布されない。
    • 詳細や利用方法はこちらのページを参照。体験版リンク#Tensor.Art
  • SeaArt (無料利用可) > https://www.seaart.ai/
    • 本社はシンガポール。
    • オンラインでSD1.5、SDXLモデルを使った画像を生成できるサービス。LoRAの利用/作成可能。
    • 生成時ポイント消費制で無課金でもデイリーポイントあり
    • pixaiの調子が悪い時に利用が増える?
    • 生成した画像が自動で公開される。月額課金、または友達招待をすると、非公開での画像生成が可能になる。
    • すけべ絵生成可
      • 25年8月時点、公開画像への規制強化により上記の非公開生成なしではプロンプトや画像への縛りが非常に厳しく、実質的にすけべ生成には課金必須。
  • 画像生成AIを利用できる生成AIサービス →体験版リンク
    • PixAI、Tensor、SeaArtの他にも多数あるので、詳しくはリンク先を参照
  • NovelAI(有料) (オススメ) →NovelAI
    • 通称「NAI」。月額制有料クラウドサービスの一つ。ブラウザ上から利用できる。UI設定に日本語あり
    • 課金必須。5ドル弱でのお試し利用から、月額25ドルでのサブスク的に出力枚数無制限のコースもある。
    • 2D美少女画像生成サービスとしてはかなり優秀で、エッチなイラストも規制なしで出すことができるのが強み。
    • プロンプトのタグはdanbooru準拠だが、記号のルール等は独自仕様。
    • ユーザーによる学習ができないため、ローカルと比べると自由度自体は低目。
    • 詳細な解説や利用方法は個別ページをどうぞ
  • Bing イメージクリエーター by Microsoft (無料) →Bing Image Creator
    • Microsoftの運営するAI画像生成サービス。
    • 日本語でのプロンプト入力も可能で、大企業パワーにより高品質な画像を簡単に作ることができる。
    • ただしすけべやセンシティブな規制はガチガチ。
    • 初音ミク、マリオ、セーラームーンといったごく一部の版権キャラクターは出るが、それ以外は無理。
    • 生成エンジンはDALL-E (2023年11月時点ではDALL-E3)。
    • 2025年8月からGPT-4oとDALL-E3が選択可能に
  • ImageFX by Google (無料)https://labs.google/fx/tools/image-fx
    • Googleのマルチモーダル*1AIモデル「Gemini」を使った画像生成サービス
    • Googleアカウントが必要
    • 生成された画像にはAI生成であることを証明するための「SynthID」なる電子透かしが埋め込まれる。
  • Grok by X (無料利用可)
    • X(旧twitter)の画像生成サービスで、モデルはGrokとFLUX.1
    • Xのアカウトが必要で、メニューから利用可能
    • 無償アカウントは2時間で10回制限アリ(2024年12月時点)、有償アカウントでの制限は不明
    • [XのAI「Grok」が無料ユーザーでも利用可能に(PC Watch) 2024年12月9日>https://pc.watch.impress.co.jp/docs/news/1645982.html]
  • ChatGPT (無料利用可)
    • AIを一躍有名にしたOpenAIのサービス
    • 以前はBingと同じくDALL-E3だったがChatGPT4oがネイティブで画像生成に対応した
    • nsfwな画像の生成は難しいがプロンプトの理解力は圧倒的
    • 制限はあるが無料アカウントでも利用可能
    • ChatGPTに彼女になってもらい、自撮りという設定で画像を生成してもらうといった遊び方もできる
    • 2025年8月現在、ChatGPTに頼むとDALL-E3で生成、左メニューからSoraに飛ぶとGPT-4oで生成
    • Soraでの動画生成は有料プランユーザーのみだが、無料ユーザーでも静止画の生成は24時間あたり12枚まで可能
  • Whisk(無料)
    • Googleが提供している実験的なサービス
    • 画像とそれをベースにした動画の生成が可能
    • nsfwな生成は困難

クラウドGPUサービス

前述のPC用アプリをGPUつよつよサーバーにインストールして使う方法。
「クラウドスペースを借りて、そこで1111を動かそうぜ!」みたいな。
PCスペックに自信の無い人でもローカル環境とおおむね同等の機能が使えるが、PCやサーバー知識がある程度必要になる。
またGPUは複数ユーザーで共有するため、あまりに長時間 高い負荷をかけ続けたりすると警告を受ける

  • Google Colab Pro(有料) →Colab版導入
    • あまりにも負荷が高かったようで、無料版での利用は禁止されてしまった
  • Paperspace →Paperspace版導入
  • Vast.ai(有料)
    • 優良サービスの中では最も安価。
      • ただし、有象無象のGPUを他人から借りている状態のため、突然遮断される可能性がある
  • Runpod.io(有料)
    • Vast.aiより高価だが、だいたい0.3USD/hのレートでRTX4090をレンタルできる。
    • 起動するたびにデータがリセットされるため、ストレージ(Network Volume)に課金してモデル等のデータを保持する必要がある。
      • ストレージの内容は運営が閲覧できないという説明になっており、プライバシー上の懸念はない(先述した通りUIに認証をかける必要はある)
    • ストレージのリージョンによって、使えるGPUが異なってくるため、作成時点で慎重に吟味する必要がある
      • GPUの選択肢が多いおすすめはEU-RO-1で、RTX2000 Ada(安価)でセットアップ→RTX4090で生成という流れができる
    • 各種ソフトは「テンプレート」を選択してインストールする形式になっており、それぞれ有志が作成したものを使うのが主流(サービス公式のものは更新が止まっている)
    • 各種ソフトのテンプレート(有志の説明記事)

(としあき製)スレ閲覧時に便利なブックマークレット

画像の埋め込み情報を表示

まずは新しいブックマークを適当に作成し、そのURLを下記のいずれかの内容に書き換えて保存してください。

ふたばフォレスト対応+動画追加版(2025/8/16版)

ふたばフォレスト対応+動画追加版(2025/8/16版)
2025/8/13版にふたばフォレストでの動画データ表示機能を追加したもの

javascript:(()=>{let dlst=["masterpiece","best quality","score_\\d+(_up)?","lowres","bad (anatomy|hands)","text","error","missing fingers","(extra|fewer) digits?","cropped","(worst|low|normal) quality","jpeg artifacts","signature","watermark","username","blurry","artist name","(high|low|worst)[\\s_]*quality","lowers","(extra|fewer|missing)[\\s_]*(fingers|arms|legs)","logo","dated","sign","word","mosaic","censored"],slst=["Model:","Negative prompt:","Version:"],e=e=>e?.length?e.split(/[\n,] (?=[\w "]+: )/).join("\n").replace(/^\s*\n/mg,""):"no info",de=async d=>(await new Response((new Blob([d])).stream().pipeThrough(new DecompressionStream("deflate"))).arrayBuffer()),r=async a=>{if(!a.target.open)return;a.target.removeEventListener("toggle",r);let l1=(new TextDecoder("latin1").decode(ab=(await(await fetch(a.target.dataset.href)).arrayBuffer()))),u8=new Uint8Array(ab),t16=((idx=l1.search(/(?<=UNICODE\0)/u))!=-1)?(ed=l1.match(/(?:eXIf|Exif\0\0|EXIF[\s\S]{2}\0\0)(..)[\s\S]*?(?=UNICODE\0)/u),sz=u8[ed.index-2]*256+u8[ed.index-1],new TextDecoder("utf-16"+((ed?.[1]=="MM"||(u8[0]==0xFF&&u8[1]==0xD8))?"be":"")).decode(sz==0?ab.slice(idx):ab.slice(idx,idx+sz))):"",o=a.target.querySelector("div"),l=[...l1.matchAll(/(?<=(?:tE|iT)Xt(?:parameters|Description|Comment|prompt)\0+)([\s\S]+?)(?=[\s\S]{4}\0)/udg)]?.map(m=>(new TextDecoder("utf-8")).decode(ab.slice(m.indices[0][0],m.indices[0][1]))),z=await Promise.all([...l1.matchAll(/zTXt(?:parameters|Description|Comment|prompt)\0+/udg)]?.map(async (m)=>{h=m.indices[0][0],t=m.indices[0][1],cs=u8[h-4]*(2**24)+u8[h-3]*(2**16)+u8[h-2]*(2**8)+u8[h-1];return (new TextDecoder("utf-8")).decode(await de(ab.slice(t,h+4+cs)))})),d=t16.match(/[^%01]*/u)?.[0]?.replace(/[\uffdb\uffc0].*?$/,"");o.innerText=e((l?.join("\n")??"")+(z?.join("\n")??"")+(d?d:""));o.innerHTML=o.innerHTML.replace(slst.length?new RegExp("("+slst.join("|")+")","g"):/(?!)/,"<strong><u>$&</u></strong>").replace(dlst.length?new RegExp("[\\[\\{\\(]*(?<!\\w)("+dlst.join("|")+")(?!\\w):?-?[\\d\\.]*[\\]\\}\\)]*[,\\s]*","g"):/(?!)/,%27<span style="opacity:0.4">$&</span>%27)},a=e=>{let t=e.parentElement;if(t.dataset.done||!/\.(png|jpg|webp)$/.test(e.href))return;let a=document.createElement("details");a.innerHTML=%27<summary style="user-select:none;cursor:pointer;">Info</summary><div style="font-family:\\"chrome\\";max-width:50vw;overflow:auto;white-space:pre-wrap">...</div>%27,a.dataset.href=e.href,a.addEventListener("toggle",r),bq=t.querySelector("blockquote"),bq&&bq.after(a),t.dataset.done=!0},n=s=>[...document.querySelectorAll(s)].forEach(a);n(".thre a:first-of-type,.c9-14 a:first-of-type");n(".rtd a:last-of-type,.c9-10 a:last-of-type");let mo1=new MutationObserver(e=>{e.forEach(e=>{if(!e.addedNodes.length)return;n(".rtd a:last-of-type")})}),l=document.querySelector(".thre");l&&mo1.observe(l,{childList:!0});const H=s=>String(s||"").replace(/[&<>"]/g,m=>({"&":"&amp;","<":"&lt;",">":"&gt;",%27"%27:"&quot;"}[m])),QS=%27a[href$=".mp4"],video[src$=".mp4"]%27,U=el=>{try{return new URL(el.tagName==="VIDEO"?(el.currentSrc||el.src):el.href,location.href).href}catch(e){return el.tagName==="VIDEO"?(el.currentSrc||el.src):el.href}},seen=new Set(),host=el=>el.closest("div,li,p,figure,.rtd,.thre,.c9-10,.c9-14")||el.parentNode||document.body,show=(el,t,txt)=>{let det=document.createElement("details");det.innerHTML=%27<summary style="user-select:none;cursor:pointer;">&#127902;%EF%B8%8FInfo</summary><div style="font-family:\\"chrome\\";max-width:50vw;overflow:auto;white-space:pre-wrap">%27+H(txt)+%27</div>%27;host(el).appendChild(det)},JP=s=>{try{return JSON.parse(s)}catch(e){return null}},strAt=(S,i)=>{let j=i+1,esc=0;for(;j<S.length;j++){let c=S[j];if(esc){esc=0;continue}if(c==="\\"){esc=1;continue}if(c==%27"%27){j++;break}}return S.slice(i,j)},objAt=(S,i)=>{let j=i,d=0,str=0,esc=0;for(;j<S.length;j++){let c=S[j];if(str){if(esc){esc=0;continue}if(c==="\\"){esc=1;continue}if(c==%27"%27){str=0}continue}if(c==%27"%27){str=1;continue}if(c=="{")d++;else if(c=="}"){d--;if(d==0){j++;break}}}return S.slice(i,j)},isLabely=t=>{t=String(t||"").trim();return (/^(TxtEmb|TextEmb)/i.test(t))||(!/\\s/.test(t)&&t.length<24)},bestStr=inp=>{if(!inp||typeof inp!=="object")return null;const pri=["populated_text","wildcard_text","prompt","positive_prompt","result","text","string","value"];for(const k of pri){const v=inp[k];if(typeof v==="string"&&v.trim())return v.trim()}let best=null;for(const k in inp){const v=inp[k];if(typeof v==="string"&&v.trim()){if(!best||v.length>best.length)best=v}}return best&&best.trim()},pickFromNodes=nodes=>{const EX=/PointMosaic|Mosaic|Mask|TxtEmb|TextEmb/i;let map={};if(Array.isArray(nodes))for(const n of nodes){if(n&&n.id!=null)map[String(n.id)]=n}const resolve=(node,depth=0)=>{if(!node||depth>4)return null;const ti=(node.title||(node._meta&&node._meta.title)||""),ct=(node.type||node.class_type||"");let s=bestStr(node.inputs);if(typeof s==="string"&&s&&!isLabely(s))return s;if(node.inputs&&typeof node.inputs==="object"){for(const k in node.inputs){const v=node.inputs[k];if(Array.isArray(v)&&map[String(v[0])]){const r=resolve(map[String(v[0])],depth+1);if(r&&!isLabely(r))return r}else if(typeof v==="string"&&v.trim()&&!isLabely(v))return v.trim()}}if(Array.isArray(node.widgets_values))for(const v of node.widgets_values){if(typeof v==="string"&&v.trim()&&!isLabely(v))return v.trim()}return null};for(const n of nodes||[]){if(!n)continue;if(/ImpactWildcardProcessor/i.test(n.type||n.class_type||"")){let s=resolve(n);if(s)return s}}for(const n of nodes||[]){if(!n)continue;if(/WanVideoTextEncodeSingle/i.test(n.type||n.class_type||"")){let s=resolve(n);if(s)return s}}for(const n of nodes||[]){if(!n)continue;if(/WanVideoTextEncode/i.test(n.type||n.class_type||"")){let s=resolve(n);if(s)return s}}for(const n of nodes||[]){if(!n)continue;let ty=n.type||n.class_type||"",tt=n.title||(n._meta&&n._meta.title)||"";if((/CLIPTextEncode|CLIP.*Text/i.test(ty))&&/Positive/i.test(tt)&&!/Negative/i.test(tt)){let s=bestStr(n.inputs);if(!s&&Array.isArray(n.widgets_values))s=n.widgets_values[0];if(typeof s==="string"&&s.trim()&&!isLabely(s))return s.trim()}}for(const n of nodes||[]){if(!n)continue;let tt=n.title||(n._meta&&n._meta.title)||"";if(EX.test(tt))continue;let s=bestStr(n.inputs);if(!s&&Array.isArray(n.widgets_values))s=n.widgets_values[0];if(typeof s==="string"&&s.trim()&&!isLabely(s)&&/Positive/i.test(tt)&&!/Negative/i.test(tt))return s.trim()}return null},scanHeu=obj=>{const EX_T=/PointMosaic|Mosaic|Mask|TxtEmb|TextEmb/i,EX_C=/ShowText|Display|Note|Preview|VHS_|Image|Resize|Seed|INTConstant|SimpleMath|Any Switch|StringConstant(?!Multiline)/i;let best=null,sc=-1e9,st=[obj];while(st.length){let x=st.pop();if(!x||typeof x!=="object")continue;let ct=x.class_type||x.type||"",ti=(x._meta&&x._meta.title)||x.title||"",v=(x.inputs&&bestStr(x.inputs))||(Array.isArray(x.widgets_values)&&x.widgets_values[0]);if(typeof v==="string"&&v.trim()){let s=(/Positive/i.test(ti)?1000:0)+(/Negative/i.test(ti)?-1000:0)+(/TextEncode|CLIPText/i.test(ct)?120:0)+(/ImpactWildcardProcessor|WanVideoTextEncodeSingle/i.test(ct)?300:0)+Math.min(220,Math.floor(v.length/8));if(EX_T.test(ti)||EX_T.test(ct))s-=900;if(EX_C.test(ct))s-=400;if(isLabely(v))s-=500;if(s>sc){sc=s;best=v.trim()}}for(const k in x){try{st.push(x[k])}catch(e){}}}return best},parse=async(u,el)=>{try{let buf=await fetch(u).then(r=>{if(!r.ok)throw new Error(r.status);return r.arrayBuffer()}),s=new TextDecoder("utf-8").decode(new Uint8Array(buf)),out=null,m,i;m=/"prompt"\s*:\s*/.exec(s);if(m){i=m.index+m[0].length;if(s[i]==%27"%27){let lit=strAt(s,i),inner=JP(lit);if(typeof inner==="string"){let obj=JP(inner);if(obj)out=pickFromNodes(obj.nodes)||scanHeu(obj)}else if(inner&&typeof inner==="object"){out=pickFromNodes(inner.nodes)||scanHeu(inner)}}else if(s[i]=="{"){let js=objAt(s,i),obj=JP(js);if(obj)out=pickFromNodes(obj.nodes)||scanHeu(obj)}}if(!out){m=/"workflow"\s*:\s*\{/.exec(s);if(m){i=m.index+m[0].length-1;let js=objAt(s,i),wf=JP(js);if(wf)out=pickFromNodes(wf.nodes)||scanHeu(wf)}}if(!out){let mm=/"CLIPTextEncode"[\s\S]{0,2000}?"title"\s*:\s*"([^"]*Positive[^"]*)"[\s\S]{0,1000}?"(text|string)"\s*:\s*"((?:\\.|[^"\\])*)"/i.exec(s);if(mm)out=mm[3].replace(/\\"/g,%27"%27)}show(el,"&#127902;%EF%B8%8FInfo",out||"prompt not found")}catch(e){show(el,"&#127902;%EF%B8%8FInfo",(e&&e.message)||String(e))}},run=el=>{let u=U(el);if(!u||seen.has(u))return;seen.add(u);parse(u,el)};document.querySelectorAll(QS).forEach(run);new MutationObserver(ms=>{ms.forEach(m=>{m.addedNodes&&m.addedNodes.forEach(n=>{if(n&&n.querySelector)n.querySelectorAll(QS).forEach(run)})})}).observe(document.body,{childList:!0,subtree:!0});})()

44 無念 Name としあき 25/08/16(土)05:36:41 ID:9EBboGVo No.1343747363 そうだねx4

>ふたばフォレスト対応+動画追加版(2025/8/13版)

>2025/6/1版に動画データ表示機能を追加したもの(ふたばフォレストでは画像のみ動作します)
ふたばフォレストの動画で表示されるよう改変
fu5444894.txt

ふたばフォレスト対応+動画追加版(2025/8/13版)

ふたばフォレスト対応+動画追加版(2025/8/13版)
2025/6/1版に動画データ表示機能を追加したもの(ふたばフォレストでは画像のみ動作します)

javascript:(()=>{let dlst=["masterpiece","best quality","score_\\d+(_up)?","lowres","bad (anatomy|hands)","text","error","missing fingers","(extra|fewer) digits?","cropped","(worst|low|normal) quality","jpeg artifacts","signature","watermark","username","blurry","artist name","(high|low|worst)[\\s_]*quality","lowers","(extra|fewer|missing)[\\s_]*(fingers|arms|legs)","logo","dated","sign","word","mosaic","censored"],slst=["Model:","Negative prompt:","Version:"],e=e=>e?.length?e.split(/[\n,] (?=[\w "]+: )/).join("\n").replace(/^\s*\n/mg,""):"no info",de=async d=>(await new Response((new Blob([d])).stream().pipeThrough(new DecompressionStream("deflate"))).arrayBuffer()),r=async a=>{if(!a.target.open)return;a.target.removeEventListener("toggle",r);let l1=(new TextDecoder("latin1").decode(ab=(await(await fetch(a.target.dataset.href)).arrayBuffer()))),u8=new Uint8Array(ab),t16=((idx=l1.search(/(?<=UNICODE\0)/u))!=-1)?(ed=l1.match(/(?:eXIf|Exif\0\0|EXIF[\s\S]{2}\0\0)(..)[\s\S]*?(?=UNICODE\0)/u),sz=u8[ed.index-2]*256+u8[ed.index-1],new TextDecoder("utf-16"+((ed?.[1]=="MM"||(u8[0]==0xFF&&u8[1]==0xD8))?"be":"")).decode(sz==0?ab.slice(idx):ab.slice(idx,idx+sz))):"",o=a.target.querySelector("div"),l=[...l1.matchAll(/(?<=(?:tE|iT)Xt(?:parameters|Description|Comment|prompt)\0+)([\s\S]+?)(?=[\s\S]{4}\0)/udg)]?.map(m=>(new TextDecoder("utf-8")).decode(ab.slice(m.indices[0][0],m.indices[0][1]))),z=await Promise.all([...l1.matchAll(/zTXt(?:parameters|Description|Comment|prompt)\0+/udg)]?.map(async (m)=>{h=m.indices[0][0],t=m.indices[0][1],cs=u8[h-4]*(2**24)+u8[h-3]*(2**16)+u8[h-2]*(2**8)+u8[h-1];return (new TextDecoder("utf-8")).decode(await de(ab.slice(t,h+4+cs)))})),d=t16.match(/[^%01]*/u)?.[0]?.replace(/[\uffdb\uffc0].*?$/,"");o.innerText=e((l?.join("\n")??"")+(z?.join("\n")??"")+(d?d:""));o.innerHTML=o.innerHTML.replace(slst.length?new RegExp("("+slst.join("|")+")","g"):/(?!)/,"<strong><u>$&</u></strong>").replace(dlst.length?new RegExp("[\\[\\{\\(]*(?<!\\w)("+dlst.join("|")+")(?!\\w):?-?[\\d\\.]*[\\]\\}\\)]*[,\\s]*","g"):/(?!)/,%27<span style="opacity:0.4">$&</span>%27)},a=e=>{let t=e.parentElement;if(t.dataset.done||!/\.(png|jpg|webp)$/.test(e.href))return;let a=document.createElement("details");a.innerHTML=%27<summary style="user-select:none;cursor:pointer;">Info</summary><div style="font-family:\\"chrome\\";max-width:50vw;overflow:auto;white-space:pre-wrap">...</div>%27,a.dataset.href=e.href,a.addEventListener("toggle",r),bq=t.querySelector("blockquote"),bq&&bq.after(a),t.dataset.done=!0},n=s=>[...document.querySelectorAll(s)].forEach(a);n(".thre a:first-of-type,.c9-14 a:first-of-type");n(".rtd a:last-of-type,.c9-10 a:last-of-type");let mo1=new MutationObserver(e=>{e.forEach(e=>{if(!e.addedNodes.length)return;n(".rtd a:last-of-type")})}),l=document.querySelector(".thre");l&&mo1.observe(l,{childList:!0});const H=s=>String(s||"").replace(/[&<>"]/g,m=>({"&":"&amp;","<":"&lt;",">":"&gt;",%27"%27:"&quot;"}[m])),QS=%27a[href$=".mp4"],video[src$=".mp4"]%27,U=el=>{try{return new URL(el.tagName==="VIDEO"?(el.currentSrc||el.src):el.href,location.href).href}catch(e){return el.tagName==="VIDEO"?(el.currentSrc||el.src):el.href}},seen=new Set(),host=el=>el.closest("div,li,p,figure,.rtd,.thre")||el.parentNode||document.body,show=(el,t,txt)=>{let det=document.createElement("details");det.innerHTML=%27<summary style="user-select:none;cursor:pointer;">&#127902;%EF%B8%8FInfo</summary><div style="font-family:\\"chrome\\";max-width:50vw;overflow:auto;white-space:pre-wrap">%27+H(txt)+%27</div>%27;host(el).appendChild(det)},JP=s=>{try{return JSON.parse(s)}catch(e){return null}},strAt=(S,i)=>{let j=i+1,esc=0;for(;j<S.length;j++){let c=S[j];if(esc){esc=0;continue}if(c==="\\"){esc=1;continue}if(c==%27"%27){j++;break}}return S.slice(i,j)},objAt=(S,i)=>{let j=i,d=0,str=0,esc=0;for(;j<S.length;j++){let c=S[j];if(str){if(esc){esc=0;continue}if(c==="\\"){esc=1;continue}if(c==%27"%27){str=0}continue}if(c==%27"%27){str=1;continue}if(c=="{")d++;else if(c=="}"){d--;if(d==0){j++;break}}}return S.slice(i,j)},isLabely=t=>{t=String(t||"").trim();return (/^(TxtEmb|TextEmb)/i.test(t))||(!/\\s/.test(t)&&t.length<24)},bestStr=inp=>{if(!inp||typeof inp!=="object")return null;const pri=["populated_text","wildcard_text","prompt","positive_prompt","result","text","string","value"];for(const k of pri){const v=inp[k];if(typeof v==="string"&&v.trim())return v.trim()}let best=null;for(const k in inp){const v=inp[k];if(typeof v==="string"&&v.trim()){if(!best||v.length>best.length)best=v}}return best&&best.trim()},pickFromNodes=nodes=>{const EX=/PointMosaic|Mosaic|Mask|TxtEmb|TextEmb/i;let map={};if(Array.isArray(nodes))for(const n of nodes){if(n&&n.id!=null)map[String(n.id)]=n}const resolve=(node,depth=0)=>{if(!node||depth>4)return null;const ti=(node.title||(node._meta&&node._meta.title)||""),ct=(node.type||node.class_type||"");let s=bestStr(node.inputs);if(typeof s==="string"&&s&&!isLabely(s))return s;if(node.inputs&&typeof node.inputs==="object"){for(const k in node.inputs){const v=node.inputs[k];if(Array.isArray(v)&&map[String(v[0])]){const r=resolve(map[String(v[0])],depth+1);if(r&&!isLabely(r))return r}else if(typeof v==="string"&&v.trim()&&!isLabely(v))return v.trim()}}if(Array.isArray(node.widgets_values))for(const v of node.widgets_values){if(typeof v==="string"&&v.trim()&&!isLabely(v))return v.trim()}return null};for(const n of nodes||[]){if(!n)continue;if(/ImpactWildcardProcessor/i.test(n.type||n.class_type||"")){let s=resolve(n);if(s)return s}}for(const n of nodes||[]){if(!n)continue;if(/WanVideoTextEncodeSingle/i.test(n.type||n.class_type||"")){let s=resolve(n);if(s)return s}}for(const n of nodes||[]){if(!n)continue;if(/WanVideoTextEncode/i.test(n.type||n.class_type||"")){let s=resolve(n);if(s)return s}}for(const n of nodes||[]){if(!n)continue;let ty=n.type||n.class_type||"",tt=n.title||(n._meta&&n._meta.title)||"";if((/CLIPTextEncode|CLIP.*Text/i.test(ty))&&/Positive/i.test(tt)&&!/Negative/i.test(tt)){let s=bestStr(n.inputs);if(!s&&Array.isArray(n.widgets_values))s=n.widgets_values[0];if(typeof s==="string"&&s.trim()&&!isLabely(s))return s.trim()}}for(const n of nodes||[]){if(!n)continue;let tt=n.title||(n._meta&&n._meta.title)||"";if(EX.test(tt))continue;let s=bestStr(n.inputs);if(!s&&Array.isArray(n.widgets_values))s=n.widgets_values[0];if(typeof s==="string"&&s.trim()&&!isLabely(s)&&/Positive/i.test(tt)&&!/Negative/i.test(tt))return s.trim()}return null},scanHeu=obj=>{const EX_T=/PointMosaic|Mosaic|Mask|TxtEmb|TextEmb/i,EX_C=/ShowText|Display|Note|Preview|VHS_|Image|Resize|Seed|INTConstant|SimpleMath|Any Switch|StringConstant(?!Multiline)/i;let best=null,sc=-1e9,st=[obj];while(st.length){let x=st.pop();if(!x||typeof x!=="object")continue;let ct=x.class_type||x.type||"",ti=(x._meta&&x._meta.title)||x.title||"",v=(x.inputs&&bestStr(x.inputs))||(Array.isArray(x.widgets_values)&&x.widgets_values[0]);if(typeof v==="string"&&v.trim()){let s=(/Positive/i.test(ti)?1000:0)+(/Negative/i.test(ti)?-1000:0)+(/TextEncode|CLIPText/i.test(ct)?120:0)+(/ImpactWildcardProcessor|WanVideoTextEncodeSingle/i.test(ct)?300:0)+Math.min(220,Math.floor(v.length/8));if(EX_T.test(ti)||EX_T.test(ct))s-=900;if(EX_C.test(ct))s-=400;if(isLabely(v))s-=500;if(s>sc){sc=s;best=v.trim()}}for(const k in x){try{st.push(x[k])}catch(e){}}}return best},parse=async(u,el)=>{try{let buf=await fetch(u).then(r=>{if(!r.ok)throw new Error(r.status);return r.arrayBuffer()}),s=new TextDecoder("utf-8").decode(new Uint8Array(buf)),out=null,m,i;m=/"prompt"\s*:\s*/.exec(s);if(m){i=m.index+m[0].length;if(s[i]==%27"%27){let lit=strAt(s,i),inner=JP(lit);if(typeof inner==="string"){let obj=JP(inner);if(obj)out=pickFromNodes(obj.nodes)||scanHeu(obj)}else if(inner&&typeof inner==="object"){out=pickFromNodes(inner.nodes)||scanHeu(inner)}}else if(s[i]=="{"){let js=objAt(s,i),obj=JP(js);if(obj)out=pickFromNodes(obj.nodes)||scanHeu(obj)}}if(!out){m=/"workflow"\s*:\s*\{/.exec(s);if(m){i=m.index+m[0].length-1;let js=objAt(s,i),wf=JP(js);if(wf)out=pickFromNodes(wf.nodes)||scanHeu(wf)}}if(!out){let mm=/"CLIPTextEncode"[\s\S]{0,2000}?"title"\s*:\s*"([^"]*Positive[^"]*)"[\s\S]{0,1000}?"(text|string)"\s*:\s*"((?:\\.|[^"\\])*)"/i.exec(s);if(mm)out=mm[3].replace(/\\"/g,%27"%27)}show(el,"&#127902;%EF%B8%8FInfo",out||"prompt not found")}catch(e){show(el,"&#127902;%EF%B8%8FInfo",(e&&e.message)||String(e))}},run=el=>{let u=U(el);if(!u||seen.has(u))return;seen.add(u);parse(u,el)};document.querySelectorAll(QS).forEach(run);new MutationObserver(ms=>{ms.forEach(m=>{m.addedNodes&&m.addedNodes.forEach(n=>{if(n&&n.querySelector)n.querySelectorAll(QS).forEach(run)})})}).observe(document.body,{childList:!0,subtree:!0});})()
ふたばフォレスト対応追加版(2025/6/1版)

ふたばフォレスト対応追加版(2025/6/1版)
2025/5/6版をふたばふたばフォレスト両対応にしたもの

javascript:(()=>{let dlst=["masterpiece","best quality","score_\\d+(_up)?","lowres","bad (anatomy|hands)","text","error","missing fingers","(extra|fewer) digits?","cropped","(worst|low|normal) quality","jpeg artifacts","signature","watermark","username","blurry","artist name","(high|low|worst)[\\s_]*quality","lowers","(extra|fewer|missing)[\\s_]*(fingers|arms|legs)","logo","dated","sign","word","mosaic","censored"],slst=["Model:","Negative prompt:","Version:"],e=e=>e?.length?e.split(/[\n,] (?=[\w "]+: )/).join("\n").replace(/^\s*\n/mg,""):"no info",de=async d=>(await new Response((new Blob([d])).stream().pipeThrough(new DecompressionStream("deflate"))).arrayBuffer()),r=async a=>{if(!a.target.open)return;a.target.removeEventListener("toggle",r);let l1=(new TextDecoder("latin1").decode(ab=(await(await fetch(a.target.dataset.href)).arrayBuffer()))),u8=new Uint8Array(ab),t16=((idx=l1.search(/(?<=UNICODE\0)/u))!=-1)?(ed=l1.match(/(?:eXIf|Exif\0\0|EXIF[\s\S]{2}\0\0)(..)[\s\S]*?(?=UNICODE\0)/u),sz=u8[ed.index-2]*256+u8[ed.index-1],new TextDecoder("utf-16"+((ed?.[1]=="MM"||(u8[0]==0xFF&&u8[1]==0xD8))?"be":"")).decode(sz==0?ab.slice(idx):ab.slice(idx,idx+sz))):"",o=a.target.querySelector("div"),l=[...l1.matchAll(/(?<=(?:tE|iT)Xt(?:parameters|Description|Comment|prompt)\0+)([\s\S]+?)(?=[\s\S]{4}\0)/udg)]?.map(m=>(new TextDecoder("utf-8")).decode(ab.slice(m.indices[0][0],m.indices[0][1]))),z=await Promise.all([...l1.matchAll(/zTXt(?:parameters|Description|Comment|prompt)\0+/udg)]?.map(async (m)=>{h=m.indices[0][0],t=m.indices[0][1],cs=u8[h-4]*(2**(8*3))+u8[h-3]*(2**(8*2))+u8[h-2]*(2**8)+u8[h-1];return (new TextDecoder("utf-8")).decode(await de(ab.slice(t,h+4+cs)))})),d=t16.match(/[^%01]*/u)?.[0]?.replace(/[\uffdb\uffc0].*?$/,"");o.innerText=e((l?.join("\n")??"")+(z?.join("\n")??"")+(d?d:""));o.innerHTML=o.innerHTML.replace(slst.length?new RegExp("("+slst.join("|")+")","g"):/(?!)/,"<strong><u>$&</u></strong>").replace(dlst.length?new RegExp("[\\[\\{\\(]*(?<!\\w)("+dlst.join("|")+")(?!\\w):?-?[\\d\\.]*[\\]\\}\\)]*[,\\s]*","g"):/(?!)/,%27<span style="opacity:0.4">$&</span>%27)},a=e=>{let t=e.parentElement;if(t.dataset.done||!/\.(png|jpg|webp)$/.test(e.href))return;let a=document.createElement("details");a.innerHTML=%27<summary style="user-select:none;cursor:pointer;">Info</summary><div style="font-family:"chrome";max-width:50vw;overflow:auto;white-space:pre-wrap">...</div>%27,a.dataset.href=e.href,a.addEventListener("toggle",r),bq=t.querySelector("blockquote"),bq&&bq.after(a),t.dataset.done=!0},n=s=>[...document.querySelectorAll(s)].forEach(a);n(".thre a:first-of-type,.c9-14 a:first-of-type");n(".rtd a:last-of-type,.c9-10 a:last-of-type");let o=new MutationObserver(e=>{e.forEach(e=>{if(!e.addedNodes.length)return;let t=e.addedNodes[0].querySelector(".rtd a:last-of-type");t&&n(".rtd a:last-of-type")})}),l=document.querySelector(".thre");l&&o.observe(l,{childList:!0})})();

37 無念 Name としあき 25/06/01(日)00:27:29 ID:dAkOJeds No.1323918612 そうだねx6

>>fu5109907.txt

>>(としあき製)スレ閲覧時に便利なブックマークレット

>>画像の埋め込み情報を表示5/6版をふたばフォレスト用に改変

>fu5110014.txt

>ふたばとふたばフォレスト両用にしてみたよ

>threとrtdがふたば

>c9-14とc9-10がふたばフォレスト
fu5110117.txt
ミスっていたので上げ直し

2025/5/6版

2025/5/6版
2024/3/15版をスレ画にも対応させたもの

javascript:(()=>{let dlst=["masterpiece","best quality","score_\\d+(_up)?","lowres","bad (anatomy|hands)","text","error","missing fingers","(extra|fewer) digits?","cropped","(worst|low|normal) quality","jpeg artifacts","signature","watermark","username","blurry","artist name","(high|low|worst)[\\s_]*quality","lowers","(extra|fewer|missing)[\\s_]*(fingers|arms|legs)","logo","dated","sign","word","mosaic","censored"],slst=["Model:","Negative prompt:","Version:"],e=e=>e?.length?e.split(/[\n,] (?=[\w "]+: )/).join("\n").replace(/^\s*\n/mg,""):"no info",de=async d=>(await new Response((new Blob([d])).stream().pipeThrough(new DecompressionStream("deflate"))).arrayBuffer()),r=async a=>{if(!a.target.open)return;a.target.removeEventListener("toggle",r);let l1=(new TextDecoder("latin1").decode(ab=(await(await fetch(a.target.dataset.href)).arrayBuffer()))),u8=new Uint8Array(ab),t16=((idx=l1.search(/(?<=UNICODE\0)/u))!=-1)?(ed=l1.match(/(?:eXIf|Exif\0\0|EXIF[\s\S]{2}\0\0)(..)[\s\S]*?(?=UNICODE\0)/u),sz=u8[ed.index-2]*256+u8[ed.index-1],new TextDecoder("utf-16"+((ed?.[1]=="MM"||(u8[0]==0xFF&&u8[1]==0xD8))?"be":"")).decode(sz==0?ab.slice(idx):ab.slice(idx,idx+sz))):"",o=a.target.querySelector("div"),l=[...l1.matchAll(/(?<=(?:tE|iT)Xt(?:parameters|Description|Comment|prompt)\0+)([\s\S]+?)(?=[\s\S]{4}\0)/udg)]?.map(m=>(new TextDecoder("utf-8")).decode(ab.slice(m.indices[0][0],m.indices[0][1]))),z=await Promise.all([...l1.matchAll(/zTXt(?:parameters|Description|Comment|prompt)\0+/udg)]?.map(async (m)=>{h=m.indices[0][0],t=m.indices[0][1],cs=u8[h-4]*(2**(8*3))+u8[h-3]*(2**(8*2))+u8[h-2]*(2**8)+u8[h-1];return (new TextDecoder("utf-8")).decode(await de(ab.slice(t,h+4+cs)))})),d=t16.match(/[^%01]*/u)?.[0]?.replace(/[\uffdb\uffc0].*?$/,"");o.innerText=e((l?.join("\n")??"")+(z?.join("\n")??"")+(d?d:""));o.innerHTML=o.innerHTML.replace(slst.length?new RegExp("("+slst.join("|")+")","g"):/(?!)/,"<strong><u>$&</u></strong>").replace(dlst.length?new RegExp("[\\[\\{\\(]*(?<!\\w)("+dlst.join("|")+")(?!\\w):?-?[\\d\\.]*[\\]\\}\\)]*[,\\s]*","g"):/(?!)/,%27<span style="opacity:0.4">$&</span>%27)},a=e=>{let t=e.parentElement;if(t.dataset.done||!/\.(png|jpg|webp)$/.test(e.href))return;let a=document.createElement("details");a.innerHTML=%27<summary style="user-select:none;cursor:pointer;">Info</summary><div style="font-family:"chrome";max-width:50vw;overflow:auto;white-space:pre-wrap">...</div>%27,a.dataset.href=e.href,a.addEventListener("toggle",r),bq=t.querySelector("blockquote"),bq&&bq.after(a),t.dataset.done=!0},n=s=>[...document.querySelectorAll(s)].forEach(a);n(".thre a:first-of-type");n(".rtd a:last-of-type");let o=new MutationObserver(e=>{e.forEach(e=>{if(!e.addedNodes.length)return;let t=e.addedNodes[0].querySelector(".rtd a:last-of-type");t&&n(".rtd a:last-of-type")})}),l=document.querySelector(".thre");l&&o.observe(l,{childList:!0})})();

150 無念 Name としあき 25/05/06(火)16:48:50 ID:Nl3/l7Wo No.1316864058 そうだねx12

>「スレ閲覧時に便利なブックマークレット」

>2024/3/15版をベースにスレ画対応させてみた
朝貼ったのは返信画面以外だと先頭スレッドのスレ画にしか反応しない&非対応ページでエラー吐いていたので微修正
fu4994509.txt

2024/4/24版

2024/4/24版
3/15版を、デフォルトで開いてある仕様に変更したもの

javascript:(()=>{let dlst=["masterpiece","best quality","score_\\d+(_up)?","lowres","bad (anatomy|hands)","text","error","missing fingers","(extra|fewer) digits?","cropped","(worst|low|normal) quality","jpeg artifacts","signature","watermark","username","blurry","artist name","EasyNegative(V2)?(?!:)","(high|low|worst)[\\s_]*quality","lowers","(extra|fewer|missing)[\\s_]*(fingers|arms|legs)","logo","dated","sign","word","mosaic","censored"],slst=["Model:","Negative prompt:","Version:"],e=e=>e?.length?e.split(/[\n,] (?=[\w "]+: )/).join("\n").replace(/^\s*\n/mg,""):"no info",de=async d=>(await new Response((new Blob([d])).stream().pipeThrough(new DecompressionStream("deflate"))).arrayBuffer()),r=async a=>{let l1=(new TextDecoder("latin1").decode(ab=(await(await fetch(a.dataset.href)).arrayBuffer()))),u8=new Uint8Array(ab),t16=((idx=l1.search(/(?<=UNICODE\0)/u))!=-1)?(ed=l1.match(/(?:eXIf|Exif\0\0|EXIF[\s\S]{2}\0\0)(..)[\s\S]*?(?=UNICODE\0)/u),sz=u8[ed.index-2]*256+u8[ed.index-1],new TextDecoder("utf-16"+((ed?.[1]=="MM"||(u8[0]==0xFF&&u8[1]==0xD8))?"be":"")).decode(sz==0?ab.slice(idx):ab.slice(idx,idx+sz))):"",o=a.querySelector("div"),l=[...l1.matchAll(/(?<=(?:tE|iT)Xt(?:parameters|Description|Comment|prompt|metadata)\0+)([\s\S]+?)(?=[\s\S]{4}\0)/udg)]?.map(m=>(new TextDecoder("utf-8")).decode(ab.slice(m.indices[0][0],m.indices[0][1]))),z=await Promise.all([...l1.matchAll(/zTXt(?:parameters|Description|Comment|prompt|metadata)\0+/udg)]?.map(async (m)=>{h=m.indices[0][0],t=m.indices[0][1],cs=u8[h-4]*(2**(8*3))+u8[h-3]*(2**(8*2))+u8[h-2]*(2**8)+u8[h-1];return (new TextDecoder("utf-8")).decode(await de(ab.slice(t,h+4+cs)))})),d=t16.match(/[^%01]*/u)?.[0]?.replace(/[\uffdb\uffc0].*?$/,"");o.innerText=e((l?.join("\n")??"")+(z?.join("\n")??"")+(d?d:""));o.innerHTML=o.innerHTML.replace(slst.length?new RegExp("("+slst.join("|")+")","g"):/(?!)/,"<strong><u>$&</u></strong>").replace(dlst.length?new RegExp("[\\[\\{\\(]*(?<!\\w)("+dlst.join("|")+")(?!\\w):?-?[\\d\\.]*[\\]\\}\\)]*[,\\s]*","g"):/(?!)/,%27<span style="opacity:0.4">$&</span>%27)},a=e=>{let t=e.parentElement;if(t.dataset.done||!/\.(png|jpg|webp)$/.test(e.href))return;let a=document.createElement("details");a.innerHTML=%27<summary style="user-select:none;cursor:pointer;">Info</summary><div style="font-family:"chrome";max-width:50vw;overflow:auto;white-space:pre-wrap">...</div>%27,a.dataset.href=e.href,t.append(a),a.open=true,t.dataset.done=!0;r(a)},n=()=>[...document.querySelectorAll(".rtd a:last-of-type")].forEach(a);n();let o=new MutationObserver(e=>{e.forEach(e=>{if(!e.addedNodes.length)return;let t=e.addedNodes[0].querySelector(".rtd a:last-of-type");t&&n()})}),l=document.querySelector(".thre");l&&o.observe(l,{childList:!0})})();

56 無念 Name としあき 24/04/24(水)20:55:47 ID:wa0pRLg2 No.1209301399 そうだねx14
たておつ
ログを読んでたら「スレ閲覧時に便利なブックマークレット」最新版の
「デフォルトで開いてある版」が欲しいということだったのでやっつけ
https://xgf.nu/5aHXj

1000レス近くを完全に読み込むには少し時間がかかる
件数があまりに多すぎると画像読み込みのところでコケるかも…?

2024/3/15版

2024/3/15版
特徴

  • png内でマルチバイト文字が化けるのを修正
  • zTXt形式に対応
  • ステップ数やサンプラー等の生成パラメータ毎に改行するので見やすい
  • 「▶Info」のクリック時に情報を取得
  • ComfyUIから出力した画像にも対応
javascript:(()=>{let dlst=["masterpiece","best quality","score_\\d+(_up)?","lowres","bad (anatomy|hands)","text","error","missing fingers","(extra|fewer) digits?","cropped","(worst|low|normal) quality","jpeg artifacts","signature","watermark","username","blurry","artist name","(high|low|worst)[\\s_]*quality","lowers","(extra|fewer|missing)[\\s_]*(fingers|arms|legs)","logo","dated","sign","word","mosaic","censored"],slst=["Model:","Negative prompt:","Version:"],e=e=>e?.length?e.split(/[\n,] (?=[\w "]+: )/).join("\n").replace(/^\s*\n/mg,""):"no info",de=async d=>(await new Response((new Blob([d])).stream().pipeThrough(new DecompressionStream("deflate"))).arrayBuffer()),r=async a=>{if(!a.target.open)return;a.target.removeEventListener("toggle",r);let l1=(new TextDecoder("latin1").decode(ab=(await(await fetch(a.target.dataset.href)).arrayBuffer()))),u8=new Uint8Array(ab),t16=((idx=l1.search(/(?<=UNICODE\0)/u))!=-1)?(ed=l1.match(/(?:eXIf|Exif\0\0|EXIF[\s\S]{2}\0\0)(..)[\s\S]*?(?=UNICODE\0)/u),sz=u8[ed.index-2]*256+u8[ed.index-1],new TextDecoder("utf-16"+((ed?.[1]=="MM"||(u8[0]==0xFF&&u8[1]==0xD8))?"be":"")).decode(sz==0?ab.slice(idx):ab.slice(idx,idx+sz))):"",o=a.target.querySelector("div"),l=[...l1.matchAll(/(?<=(?:tE|iT)Xt(?:parameters|Description|Comment|prompt)\0+)([\s\S]+?)(?=[\s\S]{4}\0)/udg)]?.map(m=>(new TextDecoder("utf-8")).decode(ab.slice(m.indices[0][0],m.indices[0][1]))),z=await Promise.all([...l1.matchAll(/zTXt(?:parameters|Description|Comment|prompt)\0+/udg)]?.map(async (m)=>{h=m.indices[0][0],t=m.indices[0][1],cs=u8[h-4]*(2**(8*3))+u8[h-3]*(2**(8*2))+u8[h-2]*(2**8)+u8[h-1];return (new TextDecoder("utf-8")).decode(await de(ab.slice(t,h+4+cs)))})),d=t16.match(/[^%01]*/u)?.[0]?.replace(/[\uffdb\uffc0].*?$/,"");o.innerText=e((l?.join("\n")??"")+(z?.join("\n")??"")+(d?d:""));o.innerHTML=o.innerHTML.replace(slst.length?new RegExp("("+slst.join("|")+")","g"):/(?!)/,"<strong><u>$&</u></strong>").replace(dlst.length?new RegExp("[\\[\\{\\(]*(?<!\\w)("+dlst.join("|")+")(?!\\w):?-?[\\d\\.]*[\\]\\}\\)]*[,\\s]*","g"):/(?!)/,%27<span style="opacity:0.4">$&</span>%27)},a=e=>{let t=e.parentElement;if(t.dataset.done||!/\.(png|jpg|webp)$/.test(e.href))return;let a=document.createElement("details");a.innerHTML=%27<summary style="user-select:none;cursor:pointer;">Info</summary><div style="font-family:"chrome";max-width:50vw;overflow:auto;white-space:pre-wrap">...</div>%27,a.dataset.href=e.href,a.addEventListener("toggle",r),t.append(a),t.dataset.done=!0},n=()=>[...document.querySelectorAll(".rtd a:last-of-type")].forEach(a);n();let o=new MutationObserver(e=>{e.forEach(e=>{if(!e.addedNodes.length)return;let t=e.addedNodes[0].querySelector(".rtd a:last-of-type");t&&n()})}),l=document.querySelector(".thre");l&&o.observe(l,{childList:!0})})();

31 無念 Name としあき 24/03/15(金)23:43:52 ID:NuEFaSos No.1195801601 そうだねx19
'スレ閲覧時に便利なブックマークレット'をさらに改良
https://xgf.nu/GjiNy

png内でマルチバイト文字が化けるのを修正
zTXt形式に対応
これである程度の範囲のメタデータをカバーできてるはず…

表示を見やすく整形した版(2024/3/3)

表示を見やすく整形した版(2024/3/3)
特徴

  • ステップ数やサンプラー等の生成パラメータ毎に改行するので見やすい
  • 「▶Info」のクリック時に情報を取得
  • ComfyUIから出力した画像にも対応
javascript:(()=>{let e=e=>e?.length?e.split(/[\n,] (?=[\w "]+: )/).join("\n").replace(/^\s*\n/mg,""):"no info",r=async a=>{if(!a.target.open)return;a.target.removeEventListener("toggle",r);let t8=(new TextDecoder("latin1").decode(ab=(await(await fetch(a.target.dataset.href)).arrayBuffer()))),t16=((idx=t8.search(/(?<=UNICODE\0)/u))!=-1)?(ed=t8.match(/(?:eXIf|Exif\0\0|EXIF[\s\S]{2}\0\0)(..)[\s\S]*?(?=UNICODE\0)/u),u8=new Uint8Array(ab),sz=u8[ed.index-2]*256+u8[ed.index-1],new TextDecoder("utf-16"+(ed?.[1]=="MM"?"be":"")).decode(sz==0?ab.slice(idx):ab.slice(idx,idx+sz))):"",o=a.target.querySelector("div"),l=t8.match(/(?<=(?:tE|iT)Xt(?:parameters|Description|Comment|prompt)\0)([\s\S]+?)(?=[\s\S]{4}\0)/ug),d=t16.match(/[^%01]*/u)?.[0]?.replace(/\uffdb.*?$/, "");o.innerText=e((l?.join("")??"")+(d?d:""));o.innerHTML=o.innerHTML.replace(/(Model|Negative prompt):/g,"<strong><u>$&</u></strong>")},a=e=>{let t=e.parentElement;if(t.dataset.done||!/\.(png|jpg|webp)$/.test(e.href))return;let a=document.createElement("details");a.innerHTML=%27<summary style="user-select:none;cursor:pointer;">Info</summary><div style="font-family:"chrome";max-width:50vw;overflow:auto;white-space:pre-wrap">...</div>%27,a.dataset.href=e.href,a.addEventListener("toggle",r),t.append(a),t.dataset.done=!0},n=()=>[...document.querySelectorAll(".rtd a:last-of-type")].forEach(a);n();let o=new MutationObserver(e=>{e.forEach(e=>{if(!e.addedNodes.length)return;let t=e.addedNodes[0].querySelector(".rtd a:last-of-type");t&&n()})}),l=document.querySelector(".thre");l&&o.observe(l,{childList:!0})})();

90 無念 Name としあき 24/03/03(日)15:13:25 ID:IXl2n5Vo No.1191807017 そうだねx15

1709446405598.jpg

'スレ閲覧時に便利なブックマークレット'を改造したので
https://xgf.nu/nYPEE

項目ごとに改行を追加(縦に長くなるけど…)
区切りになるNegative prompt:と注目するModel:を強調表示
日本語にもある程度対応
一部の形式で末尾にゴミが付いたり一部NAIにあったzTXt形式には非対応です

デフォルトで閉じてある版(以下、2023/03/17)

デフォルトで閉じてある版

javascript:(()=>{
  let exif=(str)=>{let res = "";for(let i=0;i<str.length;i=i+2){res=res+str[i]}return res;};
  const exifinfo = ()=> [...document.querySelectorAll('a[href$=".jpg"]:last-of-type, a[href$=".webp"]:last-of-type')].forEach(async e=>{
    if(!e.dataset.fetched){
      e.dataset.fetched=true;
      const m=(await(await fetch(e.href)).text()).match(/UNICODE*([^]*)/u);
      m&&(e.parentElement.innerHTML+=`<details><summary>Info</summary><pre style="white-space:pre-wrap">${exif(m[1]).replace(/&/g,'&amp;').replace(/</g, '&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&#39;')}</pre></details>`)
    }
  });
  const pnginfo = ()=> [...document.querySelectorAll('a[href$=".png"]:last-of-type')].forEach(async e=>{
    if(!e.dataset.fetched){
      e.dataset.fetched=true;
      const m=(await(await fetch(e.href)).text()).match(/(?<=Xt(?:parameters|Description|Comment)\0*)([^\0]+)/ug);
      m&&(e.parentElement.innerHTML+=`<details><summary>Info</summary><pre style="white-space:pre-wrap">${m.join('').replace(/&/g,'&amp;').replace(/</g, '&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&#39;')}</pre></details>`)
    }
  });
  exifinfo();
  pnginfo();
  const observer = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
      if (!mutation.addedNodes.length) return;
      const rtd = mutation.addedNodes[0].querySelector(".rtd");
      if (rtd) {
        exifinfo();
        pnginfo();
      }
    });
  });
  const target = document.querySelector(".thre");
  if (target) observer.observe(target, {childList: true});
})();
デフォルトで開いてある版

デフォルトで開いてある版

javascript:(()=>{
  let exif=(str)=>{let res = "";for(let i=0;i<str.length;i=i+2){res=res+str[i]}return res;};
  const exifinfo = ()=> [...document.querySelectorAll('a[href$=".jpg"]:last-of-type, a[href$=".webp"]:last-of-type')].forEach(async e=>{
    if(!e.dataset.fetched){
      e.dataset.fetched=true;
      const m=(await(await fetch(e.href)).text()).match(/UNICODE*([^]*)/u);
      m&&(e.parentElement.innerHTML+=`<details open><summary>Info</summary><pre style="white-space:pre-wrap">${exif(m[1]).replace(/&/g,'&amp;').replace(/</g, '&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&#39;')}</pre></details>`)
    }
  });
  const pnginfo = ()=> [...document.querySelectorAll('a[href$=".png"]:last-of-type')].forEach(async e=>{
    if(!e.dataset.fetched){
      e.dataset.fetched=true;
      const m=(await(await fetch(e.href)).text()).match(/(?<=Xt(?:parameters|Description|Comment)\0*)([^\0]+)/ug);
      m&&(e.parentElement.innerHTML+=`<details open><summary>Info</summary><pre style="white-space:pre-wrap">${m.join('').replace(/&/g,'&amp;').replace(/</g, '&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&#39;')}</pre></details>`)
    }
  });
  exifinfo();
  pnginfo();
  const observer = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
      if (!mutation.addedNodes.length) return;
      const rtd = mutation.addedNodes[0].querySelector(".rtd");
      if (rtd) {
        exifinfo();
        pnginfo();
      }
    });
  });
  const target = document.querySelector(".thre");
  if (target) observer.observe(target, {childList: true});
})();
レスいっぱいあると重いので▼Info開いたときに取得する版

レスいっぱいあると重いので▼Info開いたときに取得する版
勝手に改造しましたすみません
edgeのスニペットで動作確認してるのでブックマークレットで動かなかったら教えて

javascript:(()=>{
const parse = (str) => !str?.length ? 'no info' : str.split(/[\n,] (?=[\w ]+: )/).join('\n')
const exif = (str) => !str?.length ? '' : (new TextDecoder('utf-16')).decode(Uint8Array.from(str.split('').map(x => x.charCodeAt())))
const getInfo = async e => {
  if (!e.target.open) return
  e.target.removeEventListener('toggle', getInfo)
  const t=(await(await fetch(e.target.dataset.href)).text())
  const pre=e.target.querySelector('div')
  const png=t.match(/(?<=Xt(?:parameters|Description|Comment)\0*)([^\0]+)/ug)
  const webp=t.match(/UNICODE*([^]*)/u)
  pre.textContent = parse((png?.join('') ?? '') + (webp ? exif(webp[1]) : ''))
}
const addDetails = x => {
  const td = x.parentElement
  if (td.dataset.done || !/\.(png|jpg|webp)$/.test(x.href)) return
  const d = document.createElement('details')
  d.innerHTML = `<summary style="user-select:none;cursor:pointer;">Info</summary><div style="font-family:'chrome';max-width:50vw;overflow:auto;white-space:pre-wrap">...</div>`
  d.dataset.href = x.href
  d.addEventListener('toggle', getInfo)
  td.append(d)
  td.dataset.done = true
}
const refresh = () => [...document.querySelectorAll('.rtd a:last-of-type')].forEach(addDetails)
refresh()
const observer = new MutationObserver((mutations) => {
  mutations.forEach((mutation) => {
    if (!mutation.addedNodes.length) return;
    const rtd = mutation.addedNodes[0].querySelector('.rtd a:last-of-type')
    if (rtd) refresh()
  })
})
const target = document.querySelector(".thre")
if (target) observer.observe(target, {childList: true})
})()
レスいっぱいあると重いので▼Info開いたときに取得する版(圧縮版)

レスいっぱいあると重いので▼Info開いたときに取得する版(圧縮版)
ブックマークレットが1行じゃないといけないとか色々でオリジナル版が動作しないことがあったので1行に収めたバージョン
Google Chromeで動作確認済みです

javascript:(()=>{let e=e=>e?.length?e.split(/[\n,] (?=[\w ]+: )/).join("\n"):"no info",t=e=>e?.length?new TextDecoder("utf-16").decode(Uint8Array.from(e.split("").map(e=>e.charCodeAt()))):"",r=async a=>{if(!a.target.open)return;a.target.removeEventListener("toggle",r);let n=await (await fetch(a.target.dataset.href)).text(),o=a.target.querySelector("div"),l=n.match(/(?<=Xt(?:parameters|Description|Comment)\0*)([^\0]+)/ug),d=n.match(/UNICODE*([^%01]*)/u);o.textContent=e((l?.join("")??"")+(d?t(d[1]):""))},a=e=>{let t=e.parentElement;if(t.dataset.done||!/\.(png|jpg|webp)$/.test(e.href))return;let a=document.createElement("details");a.innerHTML=%27<summary style="user-select:none;cursor:pointer;">Info</summary><div style="font-family:"chrome";max-width:50vw;overflow:auto;white-space:pre-wrap">...</div>%27,a.dataset.href=e.href,a.addEventListener("toggle",r),t.append(a),t.dataset.done=!0},n=()=>[...document.querySelectorAll(".rtd a:last-of-type")].forEach(a);n();let o=new MutationObserver(e=>{e.forEach(e=>{if(!e.addedNodes.length)return;let t=e.addedNodes[0].querySelector(".rtd a:last-of-type");t&&n()})}),l=document.querySelector(".thre");l&&o.observe(l,{childList:!0})})();

これで準備はOKです。あとは「スレを開いた状態」でこのブクマを使用してみてください。
スレ全体に対して効果を発揮し、個々のレス部分に「▼Info」と表示が出て画像のメタデータ(プロンプト等)が見れるようになります。
「▼Info」部分をクリックすることで開閉できます。
後から読み込まれたレスに対しても自動で適用されるので、ブクマを再実行する必要はありません。
対応形式:png、jpg、webp
ただしNMKDで生成した画像のメタデータには未対応となります。初心者向けや1111のPNG Infoタブを利用してください。
また、モザイク処理やファイル形式の変換等によりメタデータが消失している画像の分は、もちろん表示できません。悪しからず。

※android端末でのスレ閲覧時には、URLバーを押しブックマークレットの名前を入れ選択することで使用できます。

出典
96無念Nameとしあき23/03/17(金)20:52:31 ID:/3JHyZBo[2]No.1077255473No.1077255473 ngそうだねx22
たておつkemono
ブックマークレット更新しました
あとから読み込まれたレスにも自動で反応するようにしました
もう何度もポチポチしなくても大丈夫
fu2017743.txt

NovelAIの強調をwebuiの強調に変換

NovelAIのプロンプト(呪文)をwebui等に流用したい時に役立つブクマ。

javascript:(()=>{let a=0,b='',d=0,m=0,l=0;for(const c of window.prompt('変換したいNAIのプロンプトを入力してください')){if(c=='{'){a++,m=a;if(a==1){b+='('}}else if(c=='}'){a--;if(a==0){b+=':'+(Math.round(10000*1.05**m)/10000)+')',m=0}}else if(c=='['){d++,l=d;if(d==1){b+='('}}else if(c==']'){d--;if(d==0){b+=':'+(Math.round(10000*(1/1.05)**l)/10000)+')',l=0}}else{b+=c}};window.prompt('変換しました。コピーしてください',b)})()
出典
やっつけだけどNAIの強調をwebuiの強調に変換するブックマークレット作った
入力ダイアログが出るからそこにNAIのプロンプトをコピペしてOK→変換後のプロンプトがまたダイアログで出るのでコピーする
javascript:(()=>{let a=0,b='',d=0,m=0,l=0;for(const c of window.prompt('変換したいNAIのプロンプトを入力してください')){if(c=='{'){a++,m=a;if(a==1){b+='('}}else if(c=='}'){a--;if(a==0){b+=':'+(Math.round(10000*1.05**m)/10000)+')',m=0}}else if(c=='['){d++,l=d;if(d==1){b+='('}}else if(c==']'){d--;if(d==0){b+=':'+(Math.round(10000*(1/1.05)**l)/10000)+')',l=0}}else{b+=c}};window.prompt('変換しました。コピーしてください',b)})()

埋め立て連投荒らし削除(2024/06/07版)

使い方

  1. 新しいブックマークを適当に作成
  2. そのURLを下記の内容に書き換えて保存
    javascript: (()=>{const e=a=>{if(a=a.querySelector("img")){if(!a.getAttribute("alt").match(/\d{4}/))return!1}else return!1;return!0},f=a=>{const b=a.querySelector(".idip")?.textContent?.replace(/\[\d+\]$/,"");e(a)||g(b)||!(a=a.closest("table"))||(a.style.display="none")},g=a=>{if(!a)return!1;const b=document.querySelectorAll(".rtd");if(!b)return!1;for(const c of b)if(e(c)&&(id=c.querySelector(".idip"),id?.textContent?.startsWith(a)))return!0;return!1};var d=document.querySelectorAll(".rtd");d&&(d.forEach(a=>
    {f(a)}),(d=document.querySelector(".thre"))&&(new MutationObserver(a=>{a.forEach(b=>{b.addedNodes.length&&(b=document.querySelectorAll(".rtd"))&&b.forEach(c=>{f(c)})})})).observe(d,{childList:!0}))})();
  3. 「スレを開いた状態」でこのブクマを使用

なお、FTBucketの過去ログ(過去2日分)に対しても一応利用できます。
ただしその際は「文字レス(文字だけのレス)が全て非表示」になります。

1011 無題 Name 名無し 24/06/07(金)23:26:08 ID:xZA107B2 No.59565 そうだねx11
あらら…じゃあこっちに
埋め立て連投荒らし削除ブックマークレットを追加改造して
文字だけレスでも一度でも有効な画像を投稿したIDのレスは残すようにしたよ
あんまりテストできてないけど…
fu3579102.txt

画像レス全テキスト非表示バージョン

2024/06/07版を改造したもの
画像レスの画像のみ表示で全てのテキストが表示されないタイプ

javascript: (()=> {const e = a => {if (a = a.querySelector("img")) {if (!a.getAttribute("alt").match(/\d{4}/)) return !1;} else return !1;return !0;};const f = a => {const b = a.querySelector(".idip")?.textContent?.replace(/\[\d+\]$/, "");e(a) || g(b) || !(a = a.closest("table")) || (a.style.display = "none");};const g = a => {if (!a) return !1;const b = document.querySelectorAll(".rtd");if (!b) return !1;for (const c of b) {if (e(c) && (id = c.querySelector(".idip"), id?.textContent?.startsWith(a))) return !0;}return !1;};var d = document.querySelectorAll(".rtd");d && (d.forEach(a => { f(a) }), (d = document.querySelector(".thre")) && (new MutationObserver(a => {a.forEach(b => {b.addedNodes.length && (b = document.querySelectorAll(".rtd")) && b.forEach(c => { f(c) });});})).observe(d, { childList: !0 }));d = document.querySelectorAll("blockquote").forEach(el => el.innerHTML = "");})();
過去ログ

埋め立て連投荒らし削除(2023/03/12版)
荒らし出現中に使用すると荒らしのレスは一掃されますが、副作用として荒らしではない普通の文字レスも一緒に削除されます
導入・エラーその他何かしらの質問がある時は何かしらの画像も一緒に貼り付けて質問しましょう。
なお、FTBucketの過去ログ(過去2日分)に対しても利用できます。

長いので折り畳み
javascript: (() => {
  const hide = (node) => {
    node.closest("table").style.display = "none";
  };
  const checkimg = (ele) => {
    const img = ele.querySelector("img");
    if (img) {
      const alt = img.getAttribute("alt");
      if (!alt.match(/\d{4}/)) {
        hide(ele);
      }
    } else {
      hide(ele);
    }
  };
  const res = document.querySelectorAll(".rtd");
  if (!res) return;
  res.forEach((ele) => {
    checkimg(ele);
  });
  const target = document.querySelector(".thre");
  if (!target) return;
  const observer = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
      if (!mutation.addedNodes.length) return;
      const node = mutation.addedNodes[0];
      const rtd = node.querySelector(".rtd");
      if (rtd && !node.querySelector(".rtd img")) {
        hide(node);
      } else if (rtd) {
        checkimg(rtd);
      }
    });
  });
  observer.observe(target, {
    childList: true,
  });
})();
出典
49無念Nameとしあき23/03/12(日)17:38:42 ID:b/ltdKSgNo.1075554753No.1075554753 ngそうだねx4
たておつkemono
汚物は消毒だ~ブックマークレット置いとくね
fu2002092.txt
動作は変わってないけどちょっとだけきれいに書き直しといた

動画(.mp4)にマークをつける

Framepackなどの動画のあるレスにわかりやすい絵文字(🎞️)をつける

使い方

  1. 新しいブックマークを適当に作成
  2. そのURLを下記の内容に書き換えて保存
    javascript:(function(){function e(e=document){e.querySelectorAll("table tr td.rtd").forEach(t=>{const r=t.querySelector('a[href$=".mp4"], a[href*=".mp4?"]');if(r){const e=t.querySelector("blockquote");if(e&&!e.querySelector(".video-marker")){const n=document.createElement("span");n.className="video-marker",n.textContent="\u{1F39E}\u{FE0F} ",e.insertBefore(n,e.firstChild)}}})}e();new MutationObserver(t=>{t.forEach(t=>{t.addedNodes.forEach(t=>{1===t.nodeType&&e(t)})})}).observe(document.body,{childList:!0,subtree:!0});})();
  3. 「スレを開いた状態」でこのブクマを使用
     
  • こちらは上の「画像の埋め込み情報を表示(2024/3/15版)」に動画にマーク機能を追加したもの
    javascript:(()=>{let dlst=["masterpiece","best quality","score_\\d+(_up)?","lowres","bad (anatomy|hands)","text","error","missing fingers","(extra|fewer) digits?","cropped","(worst|low|normal) quality","jpeg artifacts","signature","watermark","username","blurry","artist name","(high|low|worst)[\\s_]*quality","lowers","(extra|fewer|missing)[\\s_]*(fingers|arms|legs)","logo","dated","sign","word","mosaic","censored"],slst=["Model:","Negative prompt:","Version:"],fmt=e=>e?.length?e.split(/[\n,] (?=[\w "]+: )/).join("\n").replace(/^\s*\n/mg,""):"no info",de=async d=>(await new Response((new Blob([d])).stream().pipeThrough(new DecompressionStream("deflate"))).arrayBuffer()),parse=async d=>{let ab=await (await fetch(d)).arrayBuffer(),u8=new Uint8Array(ab),l1=(new TextDecoder("latin1").decode(ab)),idx=l1.search(/(?<=UNICODE\0)/u),ed=l1.match(/(?:eXIf|Exif\0\0|EXIF[\s\S]{2}\0\0)(..)[\s\S]*?(?=UNICODE\0)/u),sz=ed?u8[ed.index-2]*256+u8[ed.index-1]:0,t16=idx!=-1?new TextDecoder("utf-16"+((ed?.[1]=="MM"||(u8[0]==0xFF&&u8[1]==0xD8))?"be":"")).decode(sz==0?ab.slice(idx):ab.slice(idx,idx+sz)):"",txt=[...l1.matchAll(/(?<=(?:tE|iT)Xt(?:parameters|Description|Comment|prompt)\0+)([\s\S]+?)(?=[\s\S]{4}\0)/udg)].map(m=>(new TextDecoder("utf-8")).decode(ab.slice(m.indices[0][0],m.indices[0][1]))),ztxt=await Promise.all([...l1.matchAll(/zTXt(?:parameters|Description|Comment|prompt)\0+/ug)].map(async m=>{let h=m.index,t=h+4+u8[h-4]*2**24+u8[h-3]*2**16+u8[h-2]*256+u8[h-1];return new TextDecoder("utf-8").decode(await de(ab.slice(m[0].length,t)))})),d2=t16.match(/[^%01]*/u)?.[0]?.replace(/[\uffdb\uffc0].*?$/,"");return fmt((txt?.join("\n")??"")+(ztxt?.join("\n")??"")+(d2?d2:""))},addInfo=a=>{let t=a.parentElement;if(t.dataset.done||!/\.(png|jpg|webp)$/.test(a.href))return;let d=document.createElement("details");d.innerHTML='<summary style="user-select:none;cursor:pointer;">Info</summary><div style="font-family:chrome;max-width:50vw;overflow:auto;white-space:pre-wrap">読み込み中...</div>',d.dataset.href=a.href,d.addEventListener("toggle",async e=>{if(!e.target.open)return;e.target.querySelector("div").innerText=await parse(e.target.dataset.href)}),t.append(d),t.dataset.done=1},markMp4s=root=>{root.querySelectorAll("table tr td.rtd").forEach(t=>{let mp4=t.querySelector('a[href$=".mp4"], a[href*=".mp4?"]');if(mp4){let bq=t.querySelector("blockquote");if(bq && !bq.querySelector(".video-marker")){let span=document.createElement("span");span.className="video-marker";span.textContent="\u{1F39E}\u{FE0F} ";bq.insertBefore(span,bq.firstChild)}}})},init=()=>{document.querySelectorAll(".rtd a:last-of-type").forEach(addInfo);markMp4s(document)},obs=new MutationObserver(ms=>ms.forEach(m=>m.addedNodes.forEach(n=>{if(n.nodeType===1){markMp4s(n);n.querySelectorAll(".rtd a:last-of-type").forEach(addInfo)}})));init();let thr=document.querySelector(".thre");if(thr)obs.observe(thr,{childList:!0,subtree:!0})})();

ふたクロ用NGワード

FutaKuro(ふたクロ)はブラウザ用拡張機能(1111用拡張機能ではない)。
GoogleChromeやChromium派生ブラウザで利用可能。
ふたばちゃんねるでの閲覧がより快適になる。
https://futakuro.com/

スクリプト荒らし対策のNGワード設定方法

  1. ふたクロを導入後、AI絵スレを開いた状態で「NG設定」を開く
  2. ヘッダ欄に
    ^(?!.*_blank).*$
    をコピペして「正規表現」をON
  3. 「追加」ボタンを押す
  4. ヘッダ欄に
    \(\d{1,4} B\)
    をコピペして「正規表現」をON
  5. 「追加」ボタンを押す

Siki用NGワード

Sikiはふたばちゃんねるに対応した汎用掲示板ビューア(所謂2ch専用ブラウザ)です。
https://sikiapp.net/ 

Sikiの画像レスは画像URLがフルパスで本文に自動挿入されているようです。

https://may.2chan.net/b/src/123456789.png

従ってふたクロの設定に習い、画像URLがないレスを全てNGにするだけです。

スクリプト荒らし対策のNGワード設定方法。

  1. NG/強調→プルダウンメニューの「+レス条件」でNG設定を追加
  2. 検索方法→「正規表現」、否定にチェック
  3. 対象データ→「本文(body)」
  4. 対象ワード
    mayの場合
    may.*(\d+).(png|jpg|jpeg|gif|mp4|webp|webm)
  5. 保存ボタンを押して終了。

始める前に

Windowsのユーザー名は半角英数字にしよう!
(一般的に2バイト文字は避けるのが無難)


短縮URL生成

https://wikiwiki.jp/sd_toshiaki/-s/0dd28e00

*1 画像以外にも文章・音声・動画なども使えるという意味