本文へ移動
cccskills
無料GitHub で公開

mojiokoshi

取材音声・動画の文字起こしと録音管理、引用の抽出・確認を支援する。Whisper/WhisperX による音声→テキスト変換、話者分離(ダイアライゼーション)、タイムスタンプ付き原稿の作成、ファクトチェック用の引用抽出、取材源・録音のデータベース化までを扱う。

「この録音を文字起こしして」「会見の音声を整理して」「引用をタイムスタンプ付きで抜き出して」などの依頼で使う。取材前の質問設計や事前準備は shuzai-junbi スキルを使う。

sgbms1/ja-news-skillsスター 3(GitHub 3 + cccskills 0)
連携ツールOpenAIHugging Face

実行スコア 未検証

インストール方法を見る

含まれるファイル(1)

  • SKILL.md20.6 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

取材音声の文字起こしと管理

準備から出稿まで、取材の録音を扱う実務的な手順とテンプレート集。 記者の意図を聞き取り、適切なツール・手順・確認方法を提案する。引用として使う前に、必ず録音原本と突き合わせて記者が確認する。

注意:文字起こしツールの出力はあくまで下書き。固有名詞・数字・年号は誤変換が起きやすい。重要箇所は提出前に必ず原音で確認すること。本スキルは一般的な手引きであり、法的助言ではない。

いつ使うか

  • 取材音声・動画の文字起こしを行うとき
  • 文字起こし原稿を作成・整理・管理するとき
  • 複数の取材源のメモを整理するとき
  • 取材源との関係を記録するデータベースを作るとき
  • ファクトチェック用にタイムスタンプ付きの引用を作るとき
  • 録音を、出稿で使える引用に変換するとき

取材前の調査・質問設計・録音同意の取り付け・取材源との約束(オンレコ/オフレコ等)の取り決めは、shuzai-junbi(取材準備)スキルを使う。ここでは文字起こしの品質に直結する録音設定だけを扱う。

文字起こし向けの録音設定

# きれいに文字起こしするための標準的な録音設定
RECORDING_SETTINGS = {
    'format': 'wav',           # 文字起こし用にはロスレス(非圧縮)が無難
    'sample_rate': 16000,      # Whisper は内部で16kHzに変換する。16kなら容量も節約できる
    'channels': 1,             # 音声はモノラルで十分。話者ごとにマイクが分かれている場合のみステレオ
    'backup': True,            # 予備の録音機を必ず併用する
}

# ファイル名の付け方の例
# YYYY-MM-DD_取材源の姓_テーマ.wav
# 例: 2026-05-08_yamada_yosan-kaigi.wav

録音は必ず2台で。 スマートフォンを最低限の予備として、常に2台で録音する。ワイヤレスのピンマイクを使う場合、ピンマイク本体の内蔵レコーダーが1台目、バックアップアプリを動かすスマホが2台目になる。

モノラルを推奨。 話者ごとに専用マイクを別チャンネルに割り当てられる場合を除き、モノラルが無難。両話者の声が両チャンネルに混ざったステレオは、話者分離にとってきれいなモノラルより不利になる。

文字起こしの手順

自動文字起こしのパイプライン

OpenAI の素の Whisper は音声をテキストに変換するが、話者ラベルは付けない。話者ごとに分けた出力(「話者1:」「話者2:」…)を得るには、Whisper と話者分離モデルを組み合わせるツールが必要で、典型的には WhisperX(m-bain/whisperX)を使う。WhisperX は faster-whisper による文字起こしと pyannote.audio による話者分離をまとめ、単語単位のタイムスタンプと話者IDを一度に出力する。

from pathlib import Path
import subprocess
import json

def transcribe_interview(
    audio_path: str,
    output_dir: str = "./transcripts",
    diarize: bool = True,
    hf_token: str | None = None,
    min_speakers: int = 2,
    max_speakers: int = 2,
) -> dict:
    """
    WhisperX(Whisper + pyannote 話者分離)で取材音声を文字起こしする。
    単語単位のタイムスタンプと話者ラベル付きの原稿を返す。

    話者分離には pyannote の speaker-diarization-3.1 モデルへの
    アクセス権を持つ Hugging Face トークンが必要。
    huggingface.co/pyannote/speaker-diarization-3.1 で一度
    モデルの利用規約(EULA)に同意してから、トークンを渡す。
    """
    Path(output_dir).mkdir(exist_ok=True)

    cmd = [
        'whisperx', audio_path,
        '--model', 'large-v3',
        '--output_format', 'json',
        '--output_dir', output_dir,
        '--language', 'ja',           # 日本語音声は 'ja' を指定する
        '--compute_type', 'int8',     # CPU向け。GPUでは 'float16'
        '--min_speakers', str(min_speakers),
        '--max_speakers', str(max_speakers),
    ]

    if diarize:
        cmd.append('--diarize')
        if hf_token:
            cmd += ['--hf_token', hf_token]

    subprocess.run(cmd, check=True, capture_output=True)

    json_path = Path(output_dir) / f"{Path(audio_path).stem}.json"
    with open(json_path) as f:
        return json.load(f)

def format_for_editing(transcript: dict) -> str:
    """記者が編集しやすいタイムスタンプ付き形式に変換する。"""
    lines = []
    for segment in transcript.get('segments', []):
        timestamp = format_timestamp(segment['start'])
        text = segment['text'].strip()
        lines.append(f"[{timestamp}] {text}")
    return '\n\n'.join(lines)

def format_timestamp(seconds: float) -> str:
    """秒数を HH:MM:SS 形式に変換する。"""
    h = int(seconds // 3600)
    m = int((seconds % 3600) // 60)
    s = int(seconds % 60)
    return f"{h:02d}:{m:02d}:{s:02d}"

補足:日本語音声では --language ja の指定で精度が安定する。指定しないと言語自動判定で取りこぼすことがある。large-v3 系のモデルは日本語の認識精度が比較的高い。漢字変換・固有名詞の誤りは残るため、後段の整文で必ず確認する。

素の Whisper に戻す場合。 話者分離が過剰なときや、Hugging Face トークンを用意できないときは --diarize を外す。話者分離なしでもタイムスタンプ付きの文字起こしは得られるので、話者ラベルは文脈から手作業で付ける。faster-whisper(CTranslate2 バックエンド)は速度最適化版で、CLI の使い方は同じ。whisper.cpp は省リソース機向け(古いノートPC、Raspberry Pi 等)のC++移植で、話者分離は含まないが small/medium モデルをCPUで快適に動かせる。

手動文字起こしのテンプレート

機微な取材や、自動文字起こしがうまくいかない場合に使う。

## 文字起こし:[取材源] - [日付]

**録音ファイル**:[ファイル名]
**収録時間**:[XX:XX]
**文字起こし担当**:[氏名]
**録音と突き合わせ確認済み**:[ ] 済 / [ ] 未

---

[00:00:15] **問**:[質問内容]

[00:00:45] **答**:[発言:逐語。言い淀みや間は (……) と記す]

[00:01:30] **問**:[追加質問]

[00:01:42] **答**:[発言]

---

## メモ
- [音声に残らない情報:身ぶり、提示された資料、表情など]

## 引用候補
- [00:01:42] 「目を引く発言」— 文脈:[なぜ重要か]

引用の抽出と確認

引用の抜き出し手順

from dataclasses import dataclass
from typing import Optional
import re

@dataclass
class Quote:
    text: str
    timestamp: str
    speaker: str
    context: str
    verified: bool = False        # 録音と突き合わせ確認済みか
    used_in: Optional[str] = None # 使用した記事

class QuoteBank:
    """取材原稿から引用を管理する。"""

    def __init__(self):
        self.quotes = []

    def extract_quote(self, transcript: str, start_time: str,
                      end_time: str, speaker: str, context: str) -> Quote:
        """引用をメタ情報付きで抜き出して保存する。"""
        # タイムスタンプ間のテキストを取り出す
        pattern = rf'\[{re.escape(start_time)}\](.+?)(?=\[\d|$)'
        match = re.search(pattern, transcript, re.DOTALL)

        if match:
            text = match.group(1).strip()
            quote = Quote(
                text=text,
                timestamp=start_time,
                speaker=speaker,
                context=context
            )
            self.quotes.append(quote)
            return quote
        return None

    def verify_quote(self, quote: Quote, audio_path: str) -> bool:
        """録音原本と突き合わせて確認済みにする。"""
        # 実務:該当タイムスタンプの音声を聞き、正確さを確認する
        quote.verified = True
        return True

    def export_for_story(self) -> str:
        """確認済みの引用を出稿用に書き出す。"""
        output = []
        for q in self.quotes:
            if q.verified:
                output.append(f'「{q.text}」\n— {q.speaker}\n[タイムスタンプ:{q.timestamp}]')
        return '\n\n'.join(output)

引用の正確性チェックリスト

引用を記事に使う前に必ず確認する。

- [ ] 該当タイムスタンプの録音原本を聞いた
- [ ] 逐語である(要約・整文した場合はその旨を明確にした)
- [ ] 文脈が保たれている(都合よく切り取って意味を変えていない)
- [ ] 発言者を正しく特定している
- [ ] ファクトチェック担当のためにタイムスタンプを記録した
- [ ] 取材源の確認約束がある場合、引用の了解を得た
- [ ] 固有名詞・数字・年号(西暦/和暦)の誤変換を原音で確認した

日本語特有の注意:文字起こしツールは同音異義語(「保証/保障/補償」など)、人名・地名・団体名、数字・年号を取り違えやすい。引用に関わる箇所は、必ず原音で漢字・読み・数値まで確認する。表記の統一は hyoki-style スキルと連携する。

取材源の管理データベース

取材記録のデータ構造

from dataclasses import dataclass, field
from datetime import datetime
from typing import List, Optional
from enum import Enum

class SourceStatus(Enum):
    ACTIVE = "active"           # 現在やり取りがある
    DORMANT = "dormant"         # 最近接触していない
    DECLINED = "declined"       # 取材を断られた
    OFF_RECORD = "off_record"   # 背景説明のみ(オフレコ)

class InterviewType(Enum):
    ON_RECORD = "on_record"             # オンレコ(実名・所属で引用可)
    BACKGROUND = "background"           # 背景(条件付きで引用可)
    DEEP_BACKGROUND = "deep_background" # 深い背景(引用不可・記述のみ)
    OFF_RECORD = "off_record"           # オフレコ(記事に使わない)

@dataclass
class Source:
    name: str
    organization: str            # 所属
    contact_info: dict           # メール、電話、Signal など
    beat: str                    # 担当分野
    status: SourceStatus = SourceStatus.ACTIVE
    interviews: List['Interview'] = field(default_factory=list)
    notes: str = ""

    # 関係の記録
    first_contact: Optional[datetime] = None
    trust_level: int = 1         # 信頼度 1〜5

@dataclass
class Interview:
    source: str
    date: datetime
    interview_type: InterviewType
    recording_path: Optional[str] = None
    transcript_path: Optional[str] = None
    story_slug: Optional[str] = None
    key_quotes: List[str] = field(default_factory=list)
    follow_up_needed: bool = False
    notes: str = ""

取材源秘匿の注意:取材源の連絡先・実名・録音ファイルへのパスは、取材源を特定しうる情報。匿名の取材源を含むデータベースは暗号化・アクセス制限を行い、社の取材源保護方針に従って管理する。オフレコ・匿名の音声をクラウドの自動文字起こしに渡さない(後述)。

取材源の検索

def find_sources_for_story(sources: List[Source], topic: str,
                           beat: str = None) -> List[Source]:
    """新しい記事に関係しそうな取材源を探す。"""
    matches = []
    for source in sources:
        # 担当分野が指定されていれば絞り込む
        if beat and source.beat != beat:
            continue
        # 現在やり取りのある取材源のみ提案する
        if source.status != SourceStatus.ACTIVE:
            continue
        # 類似テーマで話したことがあるか確認する
        for interview in source.interviews:
            if topic.lower() in interview.notes.lower():
                matches.append(source)
                break

    # 信頼度の高い順に並べる
    return sorted(matches, key=lambda s: s.trust_level, reverse=True)

音声・動画の処理

複数録音の一括処理

from pathlib import Path
from concurrent.futures import ProcessPoolExecutor
import json

def batch_transcribe(recordings_dir: str, output_dir: str) -> dict:
    """ディレクトリ内のすべての録音を処理する。"""
    recordings = list(Path(recordings_dir).glob('*.wav')) + \
                 list(Path(recordings_dir).glob('*.mp3')) + \
                 list(Path(recordings_dir).glob('*.m4a'))

    results = {}

    with ProcessPoolExecutor(max_workers=4) as executor:
        futures = {
            executor.submit(transcribe_interview, str(rec), output_dir): rec
            for rec in recordings
        }

        for future in futures:
            rec = futures[future]
            try:
                transcript = future.result()
                results[rec.name] = {
                    'status': 'success',
                    'transcript': transcript
                }
            except Exception as e:
                results[rec.name] = {
                    'status': 'error',
                    'error': str(e)
                }

    return results

動画からの音声抽出

import subprocess

def extract_audio_from_video(video_path: str, output_path: str = None) -> str:
    """文字起こし用に動画から音声トラックを抽出する。"""
    if output_path is None:
        output_path = video_path.rsplit('.', 1)[0] + '.wav'

    subprocess.run([
        'ffmpeg', '-i', video_path,
        '-vn',                    # 映像なし
        '-acodec', 'pcm_s16le',   # WAV形式
        '-ar', '44100',           # サンプルレート
        '-ac', '1',               # モノラル
        output_path
    ], check=True)

    return output_path

法務・倫理上の注意

録音同意の記録

## 録音同意の記録

**日付**:
**取材源の氏名**:
**録音種別**:[ ] 音声 [ ] 動画
**取材区分**:[ ] オンレコ [ ] 背景 [ ] オフレコ

### 同意の取得状況
- [ ] 録音冒頭で口頭の同意を録音した
- [ ] 同意書に署名をもらった
- [ ] メールで同意の確認を得た

### 取り決めた条件
- [ ] 実名・所属での引用可
- [ ] 所属のみ明示(実名は伏せる)
- [ ] 匿名の取材源
- [ ] 掲載前に引用内容を確認してもらう
- [ ] [日付] までエンバーゴ(報道解禁前)

録音をめぐる日本での留意点

日本では、取材当事者の一方(記者本人)が同意していれば、相手の同意なく会話を録音すること自体が直ちに違法となるわけではないと一般に解されている(民事の証拠能力も、著しく反社会的な手段による場合を除き認められる傾向)。ただし、これは取材倫理上、録音の同意を取らなくてよいという意味ではない。各社の取材ガイドラインや報道倫理に従い、原則として録音すること・引用に使うことの同意を得る。隠し録音は、公益性が高く他の手段では取材できない場合に限る例外的な手法であり、社内の判断・相談が必要。

米国のような「全当事者同意(two-party consent)州」と「一方当事者同意州」の州別区分や、連邦法による上書き(preemption)、RCFP(米国報道の自由委員会)の録音ガイドは米国固有のため割愛。日本では取材源との約束(オンレコ/オフレコ等)と各社の取材倫理規程に従って判断する。

録音の同意は明示的に取り、冒頭で逐語的に記録する。 同意のやり取り(日時・発言者・応答)を各文字起こしファイルの冒頭に残す。これは法的にも自らを守り、ファクトチェック担当にとっても出発点が明確になる。

ツールと資料

ツール用途備考
OpenAI Whisperローカル文字起こし(話者分離なし)無料・オフライン動作。現行の最良モデルは large-v3。日本語は --language ja を指定
WhisperXWhisper + 話者分離m-bain/whisperX。無料。単語単位のタイムスタンプと話者ID。pyannote モデル用に Hugging Face トークンが必要
faster-whisper速度最適化版 WhisperCTranslate2 バックエンド。素の Whisper の約4倍速で精度は同等。WhisperX が内部で使用
whisper.cpp省リソース向け移植C++実装。small/medium モデルを古いPCや Raspberry Pi で動かせる
pyannote.audio単独の話者分離他のツールで作った原稿に話者分離だけ付けたいときに直接使う
MacWhisper / BuzzWhisper のGUIラッパーmacOS/クロスプラットフォームのGUI。CLIを使いたくない記者向け
Otter.aiクラウド文字起こし・リアルタイム機微な取材源に使う前にプライバシー設定を必ず確認(無断で会議参加・索引化した経緯あり)
Descript音声をテキスト感覚で編集クリップ抜き出しに便利。クラウド保存
Notta / Rimo Voice 等日本語特化のクラウド文字起こし日本語の認識に強い国内サービス。機微な音声を渡す前に保管・学習利用の規約を確認
Rev(人+AI)機微な素材向けの人手文字起こし遅いが高精度。クラウド保存
oTranscribeブラウザ完結の手動文字起こし補助ローカルのみ(アップロードなし)。クラウドに渡せないオフレコ素材向け

クラウドサービスの注意:オフレコ・匿名・機微な音源は、原則としてクラウド型サービスにアップロードしない。アップロードが避けられない場合は、保管期間・学習利用の有無・第三者提供・国外保存をサービス規約で確認し、社の方針に従う。手元で完結させるなら Whisper/WhisperX/whisper.cpp/oTranscribe のローカル系を使う。

関連スキル

  • shuzai-junbi — 取材前の調査、質問設計、録音同意の取り付け、取材源との約束(オンレコ/オフレコ等)の取り決め
  • joho-gen-kensho — 取材前に取材源の信頼性・経歴を確認する
  • fact-check — 掲載前に引用を録音と突き合わせて確認する
  • joho-kokai-seikyu — 取材の質問づくりに使う行政文書を入手する
  • data-hodo — 取材で言及されたデータを分析する
  • hyoki-style — 逐語の発言を、表記ルールに沿った出稿用の文に整える

出典・ライセンス(帰属表示)

本スキルは claude-skills-journalism(by Joe Amditis, MIT License, © 2025 Joe Amditis, https://github.com/jamditis/claude-skills-journalism )の journalism-core/interview-transcription を 原典の構成(録音設定・自動/手動の文字起こし手順・引用抽出と確認・取材源データベース・音声/動画処理・法務倫理・ツール表)に沿って日本語化し、 日本語特有の表記整理(敬語・話し言葉・同音異義・固有名詞・年号)と日本の取材実務・録音をめぐる留意点に再構成したものです。 米国の州別の録音同意法の区分・連邦法による上書き・RCFP のガイド等、米国固有の内容は日本の制度・実務に置き換えるか割愛しています。 原典の著作物本文は転載していません。原作者の公認・推奨を受けたものではありません。 MIT ライセンス全文は同梱の LICENSE-MIT.txt を参照。

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。URL は 2 つまでです。

0 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

ai-bun-shuusei

無料概要あり

AIが生成しがちな「いかにもAIっぽい」日本語の定型表現・水増し・空疎な形容を取り除き、読者の信頼を損なわない自然な文章に直す。記事・原稿・プレスリリース・告知・SNS投稿など、AIの支援を受けて書いた文章を公開前に点検するときに使う。「AI臭を消したい」「文章が機械っぽい」「人が書いたように直したい」などの依頼で使う。

sgbms1/ja-news-skills32026年7月14日 更新

data-api-catalog

無料概要あり

取材・調査・データ報道で使える無料データ源(API)のカタログ。政府統計(e-Stat)、地域経済(RESAS)、気象(気象庁)、法令(e-Gov)、企業開示(EDINET)、書誌・国会会議録(国立国会図書館)、地理空間(国土地理院)、汎用の国際API(GDELT・Open-Meteo・Wayback等)を用途別に整理し、登録要否・利用条件・選び方を示す。「無料のデータ源が欲しい」「このテーマのAPIは?」「公的データをプログラムで取りたい」といった依頼で使う。

sgbms1/ja-news-skills32026年7月14日 更新

data-hodo

無料概要あり

データ報道(データジャーナリズム)の手順を支援する。データセットの分析、グラフや地図の作成、雑然としたデータのクリーニング、統計の算出、データに基づく記事の構築に使う。「e-Statのデータを分析したい」「人口あたりで比較したい」「グラフが誤解を招かないか確認したい」「統計から記事を組み立てたい」などの依頼で使う。記者・編集者・調査担当向け。

sgbms1/ja-news-skills32026年7月14日 更新

digital-archive

無料概要あり

取材で集めた資料(開示文書・記事・SNS・反訳など)をデジタルアーカイブ化し、AIで要約・分類・エンティティ抽出・関係づけ(知識グラフ化)して横断検索できる調査基盤を作るための手引き。「取材資料を整理したい」「大量の開示文書をデータベース化したい」「人物・組織・出来事の関係を可視化したい」「調査報道のアーカイブを作りたい」などの依頼で使う。

sgbms1/ja-news-skills32026年7月14日 更新

fact-check

無料概要あり

発言・記事・SNS投稿などの主張を体系的にファクトチェックする。主張の抽出、検証可能な命題への分解、根拠の収集、当事者への確認、判定(レーティング)、記録、訂正対応までを支援する。掲載前の裏取り、ファクトチェック記事の作成、編集部の検証手順づくりに使う。「ファクトチェックして」「この発言は本当か」「裏取りの手順を」などの依頼で使う。

sgbms1/ja-news-skills32026年7月14日 更新

fact-checker-flo

無料概要あり

テキスト・記事・ウェブページの内容を、厳密な検証方法論にもとづいてファクトチェックする。検証可能な主張を抽出し、信頼できる一次情報・公的データ・検証機関と突き合わせ、各主張の真偽と確からしさ(確信度)、情報源の信頼度スコアを評価し、根拠つきの検証レポートにまとめる。「この主張を検証して」「記事をファクトチェックして」「情報源の信頼性を見て」「真偽を判定して」「誤情報か確かめて」などの依頼で使う。付属の references(信頼できる情報源/検証方法論)を参照する検証重視版。

sgbms1/ja-news-skills32026年7月14日 更新

sgbms1 のスキルをすべて見る

このスキルの問題を報告する