ニコニコ動画のコメントを調整する機能をまとめた、自分用のユーザースクリプトを公開する。
もくじ
機能
- コメントの正規表現でブロック
- Ctrl + Bで、編集画面を表示。
- 下記が元のコード。
EscはEscとして機能させたいので、キーマップを変更した。
ニコニコ動画のコメントを正規表現でNGするスクリプト(もう動かない) · GitHub
- コメント透過度調整
- Alt+Z / Alt+Xで、透過度を上昇 / 減少。
- 標準機能の透過度調整ではまだ濃すぎるので作成。
- 動画によって暗い画面or明るい画面になった時サッと調整したいことが多いので作った。
- コメントのフォントサイズを少し小さく
- デフォルトでは少し大きすぎて動画内容を覆い隠しすぎるので小さく調整。
コード
// ==UserScript==
// @name NicoCome Visualizer
// @version 0.2
// @description コメントの正規表現ブロック(Ctrl+B)・不透明度調整(Alt+Z/X)・フォントサイズサイズ調整
// @match https://www.nicovideo.jp/watch/*
// @match https://www.nicovideo.jp/watch_tmp/*
// ==/UserScript==
// 正規表現ブロック機能はこちらが元
// ニコニコ動画のコメントを正規表現でNGするスクリプト(もう動かない) · GitHub
// https://gist.github.com/roodni/40fe3d5acba899f00e7d5f618045dd91
(function() {
'use strict';
const storageKey = 'regexp_comment_ng';
const patDefault = 'うぽつ|荒らし|NG|んん~|にょ、';
let image_to_is_safe;
let patCurrent = null;
let regexp;
const updatePat = (pat) => {
if (pat !== patCurrent) {
try {
regexp = new RegExp(pat, 'i');
patCurrent = pat;
image_to_is_safe = new WeakMap();
localStorage.setItem(storageKey, pat);
console.log('NGパターンが更新された');
} catch(e) {
return false;
}
}
return true;
};
updatePat(localStorage.getItem(storageKey) ?? patDefault);
document.addEventListener('keyup', e => {
if (e.ctrlKey && e.code === 'KeyB') {
let pat = localStorage.getItem(storageKey);
while (true) {
pat = prompt('NGパターン設定', pat);
if (!pat || updatePat(pat)) {
break;
}
}
}
});
// デフォルト値を0.3に設定
let opacity = 0.3;
const STEP = 0.1;
const MIN_OPACITY = 0.1;
const MAX_OPACITY = 1.0;
// スタイルを注入(headがない場合は作成されるまで待機)
const styleElement = document.createElement('style');
const injectStyle = () => {
if (document.head) {
document.head.appendChild(styleElement);
} else {
setTimeout(injectStyle, 100);
}
};
injectStyle();
function updateOpacity() {
opacity = Math.round(opacity * 10) / 10;
// ニコニコのCanvas描画とDOM描画の両方に対応
styleElement.textContent = `
div[data-name="comment"],
.CommentRenderer {
opacity: ${opacity} !important;
}
`;
}
// キーイベントリスナー
const keyHandler = (e) => {
// 入力フォーム内は無視
if (['input', 'textarea'].includes(e.target.tagName.toLowerCase()) || e.target.isContentEditable) {
return;
}
const key = e.key.toLowerCase();
if (e.altKey && (key === 'z' || key === 'x')) {
// サイト側やブラウザのデフォルト挙動を阻止
e.preventDefault();
e.stopImmediatePropagation();
if (key === 'z' && opacity > MIN_OPACITY) {
opacity -= STEP;
} else if (key === 'x' && opacity < MAX_OPACITY) {
opacity += STEP;
}
updateOpacity();
}
};
// キャプチャフェーズ(true)で登録し、イベントがプレーヤーに届く前に奪取する
window.addEventListener('keydown', keyHandler, true);
// 初回実行
updateOpacity();
// createElementで生成されたcanvasのfillTextを監視
const canvas_to_text = new WeakMap();
const createElement = document.createElement;
document.createElement = function(tagName, ...args) {
const elem = createElement.call(this, tagName, ...args);
if (tagName === 'canvas') {
const ctx = elem.getContext('2d');
const fillText = ctx.fillText;
ctx.fillText = function(text, ...args) {
canvas_to_text.set(elem, text);
return fillText.call(this, text, ...args);
};
// サイズ調整用の設定
const scaleFactor = 0.8; // ★縮小倍率(0.8倍、20%縮小)
const targetFillColor = "#e8e8e8"; // ★文字色(例:白)
// const targetStrokeColor = "#414141"; // ★輪郭色(例:黒)
// サイズ調整を行う共通処理
const applyScaling = (context) => {
const originalFont = context.font;
const originalLineWidth = context.lineWidth;
// フォントサイズの調整(小数点も考慮)
context.font = originalFont.replace(/(\d+(\.\d+)?)px/, (match, size) => {
const newSize = parseFloat(size) * scaleFactor;
return newSize + "px";
});
// 色の調整
context.fillStyle = targetFillColor;
// context.strokeStyle = targetStrokeColor;
// 輪郭の太さの調整(デフォルトは1px)
// lineWidthが設定されている場合のみ縮小
if (originalLineWidth > 0) {
context.lineWidth = originalLineWidth * scaleFactor;
}
return { originalFont, originalLineWidth };
};
const originalFillText = ctx.fillText;
const originalStrokeText = ctx.strokeText;
// 1. fillText(塗りつぶし)のフック
ctx.fillText = function(text, x, y, maxWidth) {
const originals = applyScaling(this);
canvas_to_text.set(elem, text); // NG判定用にテキストを保持
const result = originalFillText.call(this, text, x, y, maxWidth);
// 元の状態に戻す
this.font = originals.originalFont;
this.lineWidth = originals.originalLineWidth;
return result;
};
// 2. strokeText(輪郭)のフック(修正点)
ctx.strokeText = function(text, x, y, maxWidth) {
const originals = applyScaling(this);
// ここではテキスト保持は不要(fillTextで行っているため)
const result = originalStrokeText.call(this, text, x, y, maxWidth);
// 元の状態に戻す
this.font = originals.originalFont;
this.lineWidth = originals.originalLineWidth;
return result;
};
}
return elem;
};
// コメント描画canvasのdrawImageを監視
const modifyCommentCanvas = () => {
const commentCanvas = document.querySelector('.CommentRenderer > canvas') || document.querySelector('[data-name=comment]>canvas');
console.log('cvs', commentCanvas);
if (!commentCanvas) {
setTimeout(modifyCommentCanvas, 100);
return;
}
const commentCtx = commentCanvas.getContext('2d');
const drawImage = commentCtx.drawImage;
commentCtx.drawImage = function(image, ...args) {
let is_safe = image_to_is_safe.get(image);
if (is_safe === undefined) {
const text = canvas_to_text.get(image);
if (text === undefined) {
is_safe = true;
} else {
const m = text.match(regexp);
if (m) {
console.log('NG', m[0]);
is_safe = false;
} else {
is_safe = true;
}
}
image_to_is_safe.set(image, is_safe);
}
if (is_safe) {
drawImage.call(this, image, ...args);
}
};
console.log('コメント描画のCanvasを書き換えた');
};
modifyCommentCanvas();
// 3. ページの変更を監視して、新しいCanvasが現れたら即座にパッチを当てる
const observer = new MutationObserver(() => {
// ニコニコのプレイヤー構成に合わせてセレクタを指定
const canvas = document.querySelector('.CommentRenderer > canvas') ||
document.querySelector('[data-name=comment] > canvas');
if (canvas) {
modifyCommentCanvas(canvas);
}
});
// 監視開始(body全体を監視してCanvasの登場を待つ)
observer.observe(document.body, { childList: true, subtree: true });
})();
正規表現について
何個でもNGワードを登録できる
「〇〇|✕✕|△△」のように、「 | 」で単語を囲うことで、 好きなだけブロックすることができる。
注意点
「|〇〇|✕✕|△△|」のように、行頭・行末にまで「 | 」を付けてしまうと、全てのコメントが非表示になってしまうので注意。
正規表現の使い方
- (.)\1{20}
- 20回以上同じ文字を繰り返し使用したコメントがヒットする。
- 「いけええええ」とか「飛んだああああ」とか「wwww」とかの文字をやたら長くしている邪魔なコメを消せる。
- ^なるほど$
- 特定の文字列の完全一致コメのみを消す。
標準のNG機能ではできない正規表現の強み。 - 行頭「^」から、文字列を挟んで、行末「$」までが同じコメントだけを消す。
- やたら「なるほど」が連投されている動画があるので、それだけを消して、「なるほど、〇〇ですね」など人間が打ってそうなコメントはNGしないようにする。
- 特定の文字列の完全一致コメのみを消す。
- \(汗\)
- 半角の記号は正規表現用の特殊なコマンドとして判定されてしまう。
- そのため、半角の記号をそのまま文字として認識したい場合は、「\」を左に付ける。
- その他
- 特定|原作勢|歌詞|過去タグ|逆再生|空耳|再走|中の人|批判|伏線|死ね|成仏|見納め|ゴーウィ|パチパチw|何がまずい|なにがまずい|過去タグ|ご友人|TE勢|TE勢|アンチ|ノルマ|(意味深|(意味深|貧乳|まな板|^壁$|コロナ
- 使い古されたコメや動画から逸れた話題を消す。
正規表現が実際に効いているかテストする
【コマンドテスト】コメントテスト用動画【練習用動画】 - ニコニコ動画
上記のようなテスト用の動画に消したいコメントを打って、正規表現がうまく効いているか試してみるとよい。
確認したら打ったコメントは消すこと。