ライブチャットの定型反応を 4 カテゴリ(笑・命中・評価・状態宣言)に分類する辞書とトークナイザ

公開日: 2026-05-01 著者: 君斗りんく / Kimito-Link Project ライセンス: MIT

1.背景と動機

ニコニコ生放送・YouTube Live・Twitch などのライブ配信のチャットには、自由文よりもむしろ 「定型句的な短い反応」 が圧倒的多数を占める。日本語ライブ文化では特に顕著で、配信者の発言や場面に対して視聴者が即座にぶつける反応として、語彙が事実上テンプレ化している。

たとえばニコ生における代表的な定型反応:

  • 笑反応: 草、www、www、ワロタ、コレダヲ、w
  • 命中反応: 正解、それ、それな、あ、なるほど、ですよね
  • 評価反応: ひっど、神、神回、わかる、まじか、つよい、きもい
  • 状態宣言: 監視中、待機、ROM、初見、おつ、おつー、おやすみ

これらは個別には情報量が少ないが、配信単位で集計するとその配信の空気感を表す指紋になる。「笑反応が圧倒的に多い配信」と「評価反応・命中反応が多い配信」では、同じ視聴者数でも体験している感情のプロファイルが違う。

本手法は、これら定型反応を形態素解析や機械学習を使わず、辞書ベースで 4 カテゴリに分類する軽量な実装である。Chrome 拡張機能のようにクライアントサイドで配信中にリアルタイム動作する必要がある環境で、軽量さが本質的に重要になる。

2.手法の概要

処理は以下の 4 段階で構成される:

  1. 正規化(Normalization): コメント本文を視覚的同等性に基づき短いキーに変換する(例: 「wwww」「www」「www!」→ www)。
  2. 長さ判定: 正規化後の文字数で「定型句候補」かを足切りする(基本は 8 文字以下)。
  3. カテゴリ辞書照合: 4 カテゴリそれぞれが持つ短語彙テーブルと完全一致/前方一致/部分一致のいずれかで照合する。
  4. カテゴリ集計: マッチしたコメントは該当カテゴリにカウントされる。マッチしないコメントは narrative(自由文)として別枠に集計する。

1 コメントあたりの処理は O(辞書サイズ) で、辞書が数百語規模ならば実質 O(1)。配信中のリアルタイム集計に余裕で間に合う。

3.4 カテゴリの定義と語彙

3-1. 笑反応(laugh)

「面白い」と感じた瞬間の即時反応。ライブ配信のチャットで最も多いカテゴリ。

正規化キー例(生コメ)マッチ規則
wwww / w / ww / ww / www / www / wwww...正規化後 w+ の連続
草 / 草草 / 大草原 / w 草 w「草」「大草原」を含む
warotaワロタ / ワロタ / ワロチ / ワロエナイ前方一致 ワロ
laugh笑 / 爆笑 / wktk完全一致

3-2. 命中反応(hit)

配信者の発言・展開に視聴者が「腑に落ちた」「予想が当たった」「気づいた」瞬間の反応。

正規化キーマッチ規則
正解正解 / 正解! / せいかい完全一致
あ / あっ / あ、 / ああ正規化後 1〜2 文字 + 「あ」始まり
それそれ / それな / それそれ / それだ前方一致 それ
narurodoなるほど / なるほどな / ナルホド前方一致 なるほど または カナ正規化
desuyoneですよね / そうですよね完全一致 / 部分一致

注意: 「あ」は単独文字なので false positive が起きやすい(自由文の冒頭にも頻出する)。本手法では「正規化後の文字列が または あっ で完結している」ことを条件にする(句読点・記号を除いた後)。

3-3. 評価反応(eval)

配信内容に対する視聴者の評価・感情ラベル。ポジティブ/ネガティブ両方を含む。

正規化キー極性
ひっどひっど / ひどい / ヒドイnegative
神 / 神回 / 神配信positive
つよいつよい / 強い / 強すぎpositive
きもいきもい / キモい / きしょいnegative
わかるわかる / わかります / わかりみ共感
majikaまじか / マジか / まじかよ驚き

評価反応は極性(positive/negative/共感/驚き)のメタを辞書側に持たせると、後段の集計でポジ・ネガ比率も出せる。

3-4. 状態宣言(status)

視聴者が「自分の今の状態」をチャットに宣言するコメント。content より meta な情報。

正規化キー意味
監視中監視中 / 監視 / 観察中サイレント観戦の宣言
待機待機 / 待機中 / 待ってます配信開始待ち
romROM / ろむ / ROM 中Read Only Member
初見初見 / 初見です / 初見失礼初訪問
otsuおつ / おつー / おつかれ / 乙挨拶(終了時)
oyasumiおやすみ / おやすー / 寝落ち離脱宣言

状態宣言は視聴者の入退場やエンゲージメント変化の代替シグナルとして使える。「監視中」「待機」が多い時間帯は配信の盛り上がりとは別軸の指標になる。

4.分類アルゴリズム

4-1. 正規化規則

本手法の正規化は、コメ伝染検出と共通の関数を使う:

  1. 全角 W/w → 半角 w
  2. 全文字を小文字に統一
  3. 句読点・記号(!?!?。、,.+空白)を除去
  4. 長さ 0 ならばノイズとして除外
  5. ASCII 1 文字("a" "1" 等)はノイズとして除外(漢字・ひらがな・カタカナ・絵文字 1 字は通す)

4-2. カテゴリ判定の優先順位

1 コメントが複数カテゴリにマッチする可能性がある(例: 「神草」は (eval) と (laugh) 両方にヒット)。本手法では以下の優先順位で 1 つに割り当てる:

  1. 笑反応(最優先): 「草」「www」が含まれていれば、たとえ他にも当てはまっても laugh にする。理由: 笑反応は感情の即時性が強く、複合語でも笑いが主要因。
  2. 命中反応
  3. 評価反応
  4. 状態宣言

どれにもマッチしない場合は narrative(自由文)に分類する。

4-3. マッチ規則の 3 種類

各語彙エントリは以下のいずれかの規則を持つ:

  • exact: 正規化後の文字列が完全一致。誤検出が少ないが、表記揺れに弱い。
  • prefix: 正規化後の文字列が指定キーで始まる。「ワロタ」「ワロチ」「ワロエナイ」を ワロ でカバー。
  • contains: 正規化後の文字列に指定キーを含む。「神回」「神配信」を でカバー。ただし誤検出(「神は死んだ」のような自由文)も拾うので、長さ制約を併用する。

5.参考実装(JavaScript / 純粋関数)

以下は本拡張機能で実装している方針の擬似コードである。実装本体は将来 src/lib/reactionTemplateClassifier.js として公開予定。

/** 4 カテゴリ辞書(部分抜粋) */
const CATEGORIES = {
  laugh: [
    { rule: 'regex', pattern: /^w+$/ },
    { rule: 'contains', key: '草' },
    { rule: 'prefix', key: 'ワロ' },
    { rule: 'exact', key: '笑' },
    { rule: 'exact', key: 'wktk' }
  ],
  hit: [
    { rule: 'exact', key: '正解' },
    { rule: 'regex', pattern: /^あ+っ?$/ },
    { rule: 'prefix', key: 'それ' },
    { rule: 'prefix', key: 'なるほど' },
    { rule: 'exact', key: 'ですよね' }
  ],
  eval: [
    { rule: 'prefix', key: 'ひっど', polarity: 'neg' },
    { rule: 'prefix', key: 'ひどい', polarity: 'neg' },
    { rule: 'contains', key: '神', polarity: 'pos' },
    { rule: 'prefix', key: 'つよ', polarity: 'pos' },
    { rule: 'prefix', key: 'きも', polarity: 'neg' },
    { rule: 'prefix', key: 'わかる', polarity: 'empathy' },
    { rule: 'prefix', key: 'まじか', polarity: 'surprise' }
  ],
  status: [
    { rule: 'prefix', key: '監視' },
    { rule: 'prefix', key: '待機' },
    { rule: 'exact', key: 'rom' },
    { rule: 'prefix', key: '初見' },
    { rule: 'prefix', key: 'おつ' },
    { rule: 'prefix', key: 'おやす' }
  ]
};

const CATEGORY_PRIORITY = ['laugh', 'hit', 'eval', 'status'];
const MAX_TEMPLATE_LEN = 12;  // 12 文字超は自由文扱い

/** 単一コメントを 1 カテゴリに分類 */
export function classifyReaction(text) {
  const norm = normalizeForEcho(text);
  if (!norm || norm.length > MAX_TEMPLATE_LEN) {
    return { category: 'narrative', polarity: null, key: '' };
  }
  for (const cat of CATEGORY_PRIORITY) {
    for (const entry of CATEGORIES[cat]) {
      if (matchEntry(norm, entry)) {
        return {
          category: cat,
          polarity: entry.polarity ?? null,
          key: entry.key ?? entry.pattern.source
        };
      }
    }
  }
  return { category: 'narrative', polarity: null, key: '' };
}

function matchEntry(norm, entry) {
  if (entry.rule === 'exact')    return norm === entry.key;
  if (entry.rule === 'prefix')   return norm.startsWith(entry.key);
  if (entry.rule === 'contains') return norm.includes(entry.key);
  if (entry.rule === 'regex')    return entry.pattern.test(norm);
  return false;
}

/** コメント配列から配信単位の 4 カテゴリ profile を作る */
export function aggregateReactionProfile(comments) {
  const profile = {
    laugh: 0, hit: 0, eval: 0, status: 0, narrative: 0,
    evalPolarity: { pos: 0, neg: 0, empathy: 0, surprise: 0 },
    total: 0
  };
  for (const c of comments) {
    const r = classifyReaction(c.text);
    profile[r.category] += 1;
    if (r.category === 'eval' && r.polarity) {
      profile.evalPolarity[r.polarity] = (profile.evalPolarity[r.polarity] || 0) + 1;
    }
    profile.total += 1;
  }
  return profile;
}

6.なぜこの設計なのか

6-1. なぜ形態素解析を使わないのか

形態素解析(kuromoji 等)はライブ配信のチャットには過剰な精度を要求しない代わりに過剰なコストを払う選択になる。チャットコメントは平均 5〜10 文字程度の短文で、辞書ベースの完全一致/前方一致/部分一致で 9 割以上の定型反応をカバーできる。形態素解析を持ち込むと辞書サイズ(数 MB〜十数 MB)と起動時間(数百 ms)が拡張機能のロード遅延に直結する。

6-2. なぜ ML モデルを使わないのか

分類モデル(BERT 系の感情分類など)は精度は高いが、(1) 推論時間(1 コメ数十〜百数十 ms)、(2) モデルサイズ(数十 MB〜)、(3) クライアントサイドでの推論実装の複雑さ、の 3 点でライブ配信のリアルタイム集計には不向き。本手法は 1 コメあたり数 µs で処理できる。

6-3. なぜ「優先順位による単一カテゴリ割当」なのか

マルチラベル分類(1 コメに複数カテゴリ)にすると、後段の集計が「1 コメで複数カテゴリのカウントを上げる」設計になり、合計コメ数と各カテゴリの和が合わなくなる。本手法は各コメは 1 カテゴリに帰属させることで、集計の整合性を保ち、UI 表示で「全コメ中 35% が笑反応」のような単純な比率を即座に出せるようにしている。

6-4. なぜ narrative カテゴリを別枠にするのか

定型反応にマッチしない自由文を「該当無し」として捨てるのではなく、narrative として明示的に集計する。これにより、配信単位で「定型反応が多い/少ない」自体が指標になる。話芸寄りの配信は narrative 比率が高く、リアクション寄りの配信は laugh + eval 比率が高い、という傾向が出る。

7.応用例と限界

7-1. 応用例

  • 配信単位の感情プロファイル可視化: 4 カテゴリ + narrative の比率を円グラフ/積み上げ棒グラフで表示。
  • 配信間の比較: 同じ配信者の過去 10 配信の laugh 比率を時系列でプロットして話芸傾向を観察。
  • 盛り上がり区間の同定: 30 秒バケットごとに laugh 比率を集計し、ピーク区間を切り出す。コメ伝染検出と組み合わせると更に精度が上がる。
  • 視聴者層の推定: status カテゴリの「監視中」「ROM」が多い配信はサイレント観戦比率が高いと推定できる(自己宣言した人だけだが、傾向は出る)。
  • ネガティブ比率モニタリング: eval カテゴリの polarity が neg に偏っている時間帯を検出して、配信者にフィードバックする。

7-2. 限界

  • 新語・スラングへの追従: 辞書ベースなので、新語が出るたびに辞書を更新する必要がある。半自動で頻出 narrative を抽出して人間が振り分ける運用が現実的。
  • 文脈依存の分類: 「神」が皮肉で使われる場合(「神かよ(笑)」)など、文脈依存の極性反転は検出できない。これを精緻にやるには ML が必要。
  • 言語固定: 本手法は日本語ライブの語彙に最適化されている。他言語ライブでは語彙テーブルを差し替える必要がある(規則の枠組み自体は流用可能)。
  • 誤検出の許容: 自由文の中にたまたま「草」が含まれる(例: 「雑草」)と laugh と誤分類される。本手法は「短さ」(MAX_TEMPLATE_LEN 制約)でこれを抑制するが、完全には避けられない。集計ベースで使う限りは許容範囲。

8.公知化と実装公開

本記事および本記事で参照する将来公開予定のソースコード(src/lib/reactionTemplateClassifier.js および関連辞書ファイル)は MIT ライセンスのもと GitHub で公開する予定である。本記事の公開日 2026-05-01 をもって、本手法は世の中に対して公知になったものとして位置づける。同様の手法を別の主体が後から特許出願した場合、本記事および本記事で参照するコミット履歴が先行技術として参照可能になることを意図している(防御的公開/defensive publication)。

本手法はコメ伝染検出沈黙ゾーン検出と組み合わせることで、配信単位の感情・反応・沈黙の三次元プロファイルを構成できる。