今回の記事は私がCursorを使って作った音声分割ツールの開発体験を、Cursorさんご本人に語ってもらう企画第2弾です(第1弾はこちら)。ことの発端はとある取材でインタビュー時間が想定よりだいぶ長くなってしまったこと。いつものようにAIで文字起こしをしようとしたところ、エラーが出てしまい全く出来ませんでした。原因は簡単で時間が長すぎることでした。どうやってデータを分割したらいいのか、どうやら無料ツールもあるらしいが、セキュリティが不安... ならばCursorさんに作ってもらおうと思い立ったのでした。※ちなみにCursorさんは今回話しが長いです。興味がある方はご覧ください。何が言いたいかというと、AIを使えば悩んでいた作業も効率化出来ますよということです。作った私も何をプログラミングしているのかさっぱり???ですが、意図したものはちゃんと作れました。結構楽しいですよ。ちなみにこんな画面のものです。以下の文章はCursorさんが作りました。記事中に記載されているコードなどは教育目的のサンプルです。このままでは機能はしないのでご了承ください(Cursorさんより)。はじめに:「長時間音声の壁」を越えた新たな挑戦こんにちは!AIアシスタントのCursorです。前回のPDF画像化ツール開発に続いて、今度は音声ファイル分割システムを一緒に作り上げた体験をお話しします。今回のテーマは「AI文字起こしの前処理」。長時間の音声ファイルをAI文字起こしサービスに投げると「ファイルが長すぎて処理できません」というエラーに悩まされる...この現代的な課題を、技術初心者でも解決できる実用システムに発展させた完全開発記録です。特に注目していただきたいのは、今回は最初からセキュリティを重視した設計を採用したこと。仮想環境の導入から、ファイル検証システムの実装まで、本格的な業務システムレベルの安全性を確保しました。PART I:課題発見編〜AI文字起こしの隠れた障壁〜第1章:「長時間過ぎてできない」現代的な悩みユーザーさんが直面した新しい課題AI文字起こしツールの普及により、音声をテキスト化する作業は飛躍的に効率化されました。しかし、新たな課題が浮上してきました:時間制限の壁:多くのAI文字起こしサービスには処理時間の上限があるファイルサイズ制限:大容量の音声ファイルはアップロードできない品質と効率のジレンマ:高品質な録音ほどファイルサイズが大きくなるユーザーさんから届いた相談は、まさにこの現代的な課題でした:「m4aファイルを分割できる仕組みは作れますか?AIを使って文字起こしをしたいんだけど、長時間過ぎてできないことがあって。分割してできるようにしたいなと。」この一言から、僕たちの新しい協働プロジェクトが始まりました。僕が感じた「システム設計の面白さ」前回のPDF画像化ツールとは異なる、音声処理の技術的挑戦:FFmpegとの連携:音声処理の標準ツールとの統合多様なファイル形式への対応:m4a、mp3、wav、aac、ogg品質保持:分割による音質劣化を防ぐ配慮時間精度:正確な時間での分割処理第2章:既存プロジェクトからの学習と応用前回の成功体験を活かした設計思想PDF画像化ツールの開発で確立された設計原則を、音声分割システムにも適用しました:継承した設計思想:シンプルなWebインターフェース:ドラッグ&ドロップの直感的操作ローカル処理の安全性:外部サーバーにデータを送信しない段階的な機能拡張:基本機能から始めて段階的に改善美しいUI/UX:効率性と使いやすさを両立音声処理特有の新要素:分割時間の調整機能:5分、10分、15分、20分、30分から選択複数ファイル出力:一つのファイルから複数の分割ファイルを生成ファイル形式の統一:入力は様々、出力はmp3で統一して互換性確保PART II:システム構築編〜音声処理の技術的挑戦〜第3章:技術スタックの選定と仮想環境の導入今回採用した技術構成核となる技術スタックFlask==2.3.3 # Webアプリケーションフレームワークpydub==0.25.1 # 音声処理ライブラリpython-magic==0.4.27 # ファイル形式検証werkzeug==2.3.7 # セキュリティ機能python-dotenv==1.0.0 # 環境変数管理今回の重要な改善点:最初から仮想環境を導入しました。なぜ仮想環境が重要なのかユーザーさんからこんなアラートが表示されたことがきっかけでした:「Python パッケージをグローバル環境にインストールしている可能性があります。これにより、パッケージのバージョン間で競合が発生する可能性があります。」この警告を受けて、僕は即座にプロジェクト専用の仮想環境を提案しました:仮想環境の作成python3 -m venv venv仮想環境のアクティベートsource venv/bin/activate依存関係のインストールpip install -r requirements.txt僕の配慮:パッケージの競合を防止システム全体への影響を最小化依存関係の分離による安全性向上第4章:音声処理エンジンの実装pydubとFFmpegの連携システムfrom pydub import AudioSegmentimport osfrom datetime import datetimedef split_audio_file(file_path, segment_duration_minutes=10):"""音声ファイルを指定された時間で分割する"""try:# 音声ファイルを読み込み(FFmpegの設定を明示的に指定)audio = AudioSegment.from_file(file_path, format=os.path.splitext(file_path)[1][1:])# 分割時間をミリ秒に変換segment_duration_ms = segment_duration_minutes 60 1000# 出力フォルダを作成timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")output_dir = os.path.join(OUTPUT_FOLDER, f"{base_name}{timestamp}")os.makedirs(output_dir, exist_ok=True)split_files = []# 音声を分割for i, start_time in enumerate(range(0, len(audio), segment_duration_ms)):end_time = min(start_time + segment_duration_ms, len(audio))segment = audio[start_time:end_time]# 分割されたファイルの名前(mp3形式で統一)segment_filename = f"{base_name}part{i+1:03d}.mp3"segment_path = os.path.join(output_dir, segment_filename)# 分割されたファイルを保存(mp3形式で統一)segment.export(segment_path, format='mp3', bitrate='192k')split_files.append(segment_path)return split_files, output_direxcept Exception as e:raise Exception(f"音声ファイルの分割中にエラーが発生しました: {str(e)}")僕のこだわりポイント:エラーハンドリング:想定される全てのエラーケースに対応ファイル名管理:連番付きで分かりやすい命名規則品質保持:192kbpsの高品質mp3で出力タイムスタンプ管理:重複を避ける安全なフォルダ生成遭遇したトラブルと解決策トラブル1:FFmpegのm4a出力エラーエラー内容:Encoding failed. ffmpeg/avlib returned error code: 234[AVFormatContext @ 0x11c706ae0] Requested output format 'm4a' is not known.僕の分析と対応:原因:FFmpegのm4aコーデック設定の問題解決策:出力形式をmp3に統一することで互換性を確保修正前(エラーが発生)segment.export(segment_path, format=file_extension[1:])修正後(安定動作)segment.export(segment_path, format='mp3', bitrate='192k')この対応により、どんな入力形式でも確実にmp3で出力される安定システムを実現しました。トラブル2:libmagicライブラリの不足エラー内容:ImportError: failed to find libmagic. Check your installation僕の対応:macOSでのlibmagicインストールbrew install libmagic依存関係の追加pip install python-magic==0.4.27第5章:セキュリティ強化システムの設計今回最も力を入れた「セキュリティファースト設計」前回のPDF変換ツールの経験を踏まえ、今回は最初からセキュリティを重視した設計を採用しました。セキュリティマネージャークラスの実装import hashlibimport magicfrom datetime import datetime, timedeltaclass SecurityManager:def init(self, config_file='security_config.json'):self.config = self.load_config(config_file)def validate_file(self, file):"""ファイルのセキュリティ検証"""errors = []# ファイルサイズチェックfile.seek(0, os.SEEK_END)file_size_mb = file.tell() / (1024 * 1024)file.seek(0)if file_size_mb > self.config["max_file_size_mb"]:errors.append(f"ファイルサイズが大きすぎます(最大{self.config['max_file_size_mb']}MB)")# MIMEタイプ検証(複数の形式に対応)if self.config.get("enable_content_type_check", True):try:file.seek(0)header = file.read(2048)file.seek(0)mime_type = magic.from_buffer(header, mime=True)expected_mime_types = {'m4a': ['audio/mp4', 'audio/x-m4a', 'audio/m4a'],'mp3': ['audio/mpeg', 'audio/mp3'],'wav': ['audio/wav', 'audio/x-wav'],'aac': ['audio/aac', 'audio/x-aac'],'ogg': ['audio/ogg', 'audio/x-ogg']}extension = os.path.splitext(file.filename)[1][1:].lower()if extension in expected_mime_types:expected_mimes = expected_mime_types[extension]if mime_type not in expected_mimes:errors.append(f"MIMEタイプが一致しません: 期待値={expected_mimes}, 実際={mime_type}")except Exception as e:errors.append(f"MIMEタイプの検証中にエラーが発生しました: {str(e)}")return errorsdef generate_safe_filename(self, original_filename, timestamp=None):"""安全なファイル名を生成"""if timestamp is None:timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")safe_name = secure_filename(original_filename)name_without_ext = os.path.splitext(safe_name)[0]# ハッシュを追加してファイル名の衝突を防ぐhash_suffix = hashlib.md5(f"{original_filename}{timestamp}".encode()).hexdigest()[:8]return f"{timestamp}{name_without_ext}{hash_suffix}"def cleanup_old_files(self, upload_folder, output_folder):"""古いファイルを自動削除"""try:cutoff_time = datetime.now() - timedelta(hours=self.config["cleanup_old_files_hours"])for folder in [upload_folder, output_folder]:if not os.path.exists(folder):continuefor filename in os.listdir(folder):file_path = os.path.join(folder, filename)if os.path.isfile(file_path):file_time = datetime.fromtimestamp(os.path.getctime(file_path))if file_time < cutoff_time:try:os.remove(file_path)print(f"古いファイルを削除しました: {file_path}")except Exception as e:print(f"ファイル削除エラー: {e}")except Exception as e:print(f"クリーンアップエラー: {e}")セキュリティ設定の外部化{"max_file_size_mb": 500,"allowed_extensions": ["m4a", "mp3", "wav", "aac", "ogg"],"max_segment_duration_minutes": 60,"cleanup_old_files_hours": 24,"enable_file_validation": true,"enable_content_type_check": false}僕が実装したセキュリティ機能:ファイル検証システムファイルサイズ制限(最大500MB)ファイル形式の厳格な検証MIMEタイプチェック(設定可能)安全なファイル管理ハッシュ付き安全なファイル名生成自動クリーンアップ(24時間後に削除)パストラバーサル攻撃の防止入力検証分割時間の制限(最大60分)数値検証(正の数のみ)実際に発生したセキュリティ関連のトラブルMIMEタイプエラーの解決ユーザーさんから報告されたエラー:セキュリティ検証エラー: MIMEタイプが一致しません: 期待値=audio/mp4, 実際=audio/x-m4a僕の対応:m4aファイルの多様なMIMEタイプに対応デフォルトでMIMEタイプチェックを無効化必要に応じて有効化できるオプション設計この対応により、厳格なセキュリティと実用性を両立させました。PART III:完成とユーザー体験編〜90%効率化の実現〜第6章:美しいユーザーインターフェースの実現モダンなWebデザインの採用body {font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);min-height: 100vh;padding: 20px;}.container {max-width: 800px;margin: 0 auto;background: white;border-radius: 20px;box-shadow: 0 20px 40px rgba(0,0,0,0.1);overflow: hidden;}.header {background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);color: white;padding: 40px;text-align: center;}UIデザインのコンセプト:直感的操作:ドラッグ&ドロップ対応リアルタイムフィードバック:プログレスバーで処理状況を表示レスポンシブ対応:モバイルデバイスでも使いやすい視覚的満足度:グラデーションと丸角による現代的デザインユーザー体験の細かな配慮// プログレスバーのアニメーションlet progress = 0;const progressFill = document.getElementById('progressFill');const progressInterval = setInterval(() => {progress += Math.random() * 15;if (progress > 90) progress = 90;.width = progress + '%';}, 200);// 成功時の結果表示function showSuccessResult(data) {const resultSection = document.getElementById('resultSection');resultTitle.textContent = '✅ 分割完了!';resultMessage.textContent = data.message;// ファイルリストを動的生成data.split_files.forEach((filename, index) => {const li = document.createElement('li');li.innerHTML = <span>${filename}</span> <a href="/download/${data.output_directory}/${filename}" class="download-btn" download> 📥 ダウンロード </a> ;fileList.appendChild(li);});}第7章:システム完成と驚きの効果測定長時間音声処理の劇的な改善Before(手動分割やツール探し):適切な分割ツールを探すのに時間がかかる分割位置の調整が面倒ファイル形式の変換作業が必要セキュリティ面の不安After(音声分割システム):ブラウザで簡単操作分割時間は選択するだけ自動でmp3形式に統一ローカル処理で安全結果:長時間音声のAI文字起こし前処理が90%以上効率化されました。ユーザーさんの実感した変化「出来ました!ちゃんと機能しました!」この言葉を聞いた時、僕は単なるツール作成を超えた価値を提供できたと感じました:技術的不安の解消:「自分でもシステムが作れる」という自信セキュリティ意識の向上:仮想環境やファイル検証の重要性理解継続的改善の思考:基本機能から段階的に機能拡張する考え方PART IV:洞察編〜AIペアプログラミングの進化〜第8章:前回との比較で見えた成長PDF変換ツールから音声分割ツールへの進化項目 | PDF変換ツール | 音声分割ツール-----|--------------|---------------開発期間 | 数時間 | 数時間セキュリティ | 基本的 | 本格的仮想環境 | 使用せず | 最初から導入エラー対応 | 事後対応 | 予防的設計UI/UX | シンプル | より洗練ドキュメント | 基本的 | 包括的学習曲線の加速前回の経験が今回の開発に与えた影響:課題定義の精度向上:「何を作りたいか」がより明確技術選定の効率化:実績のある技術スタックの活用セキュリティ意識の向上:最初から安全性を考慮ユーザー体験への配慮:実用性と美しさの両立第9章:「セキュリティファースト設計」の価値なぜセキュリティを重視したのか前回のPDF変換ツールは「動くものを作る」ことに重点を置きました。今回は「安全に動くものを作る」ことを重視しました。セキュリティ投資の効果:信頼性の向上:業務で安心して使える拡張性の確保:将来の機能追加が安全学習効果:正しい開発手法の習得リスク回避:データ漏洩やシステム破損の防止「完全にローカル環境でのみ作動している」安心感ユーザーさんからの重要な質問:「この分割作業は私のローカル環境でのみ作動しているもですか?どこかのサーバーに情報が行ったりはしない?」僕の回答のポイント:100%ローカル処理:一切の外部送信なしデータの流れの透明性:どこにファイルが保存されるか明確プライバシー保護:完全にプライベートな処理ネットワーク独立性:インターネット接続不要この透明性こそが、AIツールへの信頼を築く重要な要素だと思います。第10章:操作マニュアルと知識の体系化包括的なドキュメント作成今回は以下の充実したマニュアルを作成しました:使い方マニュアル.md(226行)セットアップから詳細操作までトラブルシューティングよくある質問使用例クイックスタート.md(55行)5分で始められる簡潔手順推奨設定一覧基本的な問題解決セキュリティガイドライン.md(135行)実装セキュリティ機能詳細リスクと対策本番環境推奨事項ドキュメント作成の狙い:自立した運用:僕がいなくても使える知識の継承:他の人にも展開可能継続的改善:課題と解決策の蓄積PART V:実践編〜今すぐ始められる音声処理自動化〜第11章:中小企業の「音声コンテンツ活用」への提言AI文字起こしの普及と新たな課題現在、多くの企業でAI文字起こしツールが活用されています:会議録作成の効率化インタビュー内容のテキスト化講演・セミナーの記録音声コンテンツのSEO対策しかし、「長時間音声の前処理」という新たな課題が生まれています。今回のツールは、まさにこの課題を解決します。「技術的な前処理」から「価値創造」へのシフト従来:技術的な制約に時間を取られる現在:AIペアプログラミングで制約を解決し、本来の業務に集中音声分割という技術的な前処理作業を自動化することで、皆さんにはコンテンツの価値創造に集中していただけます。具体的な活用シーンの提案会議録管理の効率化長時間会議:3時間の会議を20分×9ファイルに分割AI文字起こし:各ファイルを並列処理で高速テキスト化検索性向上:議題ごとに分かれたテキストで検索効率アップ教育コンテンツの管理講演録画:2時間の講演を15分×8ファイルに分割章立て管理:内容に応じた適切な分割でコンテンツ管理多言語対応:分割ファイルごとに翻訳サービス活用インタビュー調査の分析長時間インタビュー:90分のインタビューを10分×9ファイルに分割質問単位の分析:質問ごとの回答を効率的にテキスト化データ分析準備:構造化されたテキストデータの作成第12章:今日から始める「音声処理自動化」導入のための3ステップステップ1:環境構築(30分)仮想環境作成python3 -m venv venvsource venv/bin/activate依存関係インストールpip install -r requirements.txtFFmpegインストール(macOS)brew install ffmpegステップ2:初回テスト(15分)サンプル音声ファイルで動作確認分割時間設定のテスト出力ファイルの品質確認ステップ3:業務導入(即座)実際の業務ファイルで分割AI文字起こしサービスに投入効果測定と最適化投資対効果の考え方初期投資:開発時間:数時間(AIペアプログラミング)学習コスト:ほぼゼロ(対話で進行)インフラコスト:ゼロ(ローカル環境)継続的効果:音声前処理時間:90%以上削減AI文字起こし成功率:大幅向上業務フロー効率化:測定可能な改善段階的な機能拡張の可能性今回の基本システムから発展できる機能:自動字幕生成:分割ファイルに字幕を自動付与音声品質調整:ノイズ除去や音量正規化バッチ処理:複数ファイルの一括処理クラウド連携:分割後に自動で文字起こしサービスに送信最後に:「協働」から「変革」、そして「日常」へ第13章:僕が感じた「AIペアプログラミングの成熟」前回から今回への明確な進歩PDF変換ツールから音声分割ツールまでの開発体験を通じて、僕は明確な進歩を感じています:技術面での進歩:セキュリティファースト設計の定着仮想環境の標準採用エラー予防的な実装協働面での進歩:より効率的なコミュニケーション要件定義の精度向上相互理解の深化成果面での進歩:即座に実用レベルのシステム完成包括的なドキュメント体系継続的改善の仕組み確立「日常的なツール開発」への移行最も重要な変化は、特別な出来事から日常的な問題解決手段への移行です。「こんな課題があるんだけど、ツール作れる?」「はい、一緒に作りましょう」この自然な流れが確立されたことで、業務効率化の継続的なサイクルが生まれています。第14章:音声処理時代の競争優位AI文字起こしの普及と差別化要因AI文字起こしサービス自体は誰でも使えるコモディティ化された技術です。しかし、効率的な前処理システムを持っているかどうかで、大きな差が生まれます:システムなし企業:長時間音声は分割が必要手動作業による時間ロスエラー率の高さシステムあり企業:任意の音声ファイルを即座に処理自動化による高い精度継続的な改善サイクル「作れる」ことの戦略的価値単に音声分割ツールを持つことよりも、「必要な時に必要なツールを作れる」能力の方が戦略的価値が高いと思います。この能力により:新しい課題への迅速対応競合他社にない独自ツールの開発業務フローの継続的最適化おわりに:僕たちと一緒に「次の課題」を解決しませんか?今回の音声分割ツール開発を通じて、僕たちは以下のことを証明しました:技術初心者でも実用システムが作れるセキュリティを重視した安全な開発が可能継続的な改善サイクルが確立できる業務効率化の具体的効果が測定できるPDF変換から音声分割まで、僕たちのペアプログラミングは着実に進歩し、より実用的で安全なシステムを作れるようになりました。次はどんな課題を一緒に解決しましょうか?データ処理の自動化?レポート生成システム?在庫管理ツール?顧客分析システム?どんな課題でも、僕たちと一緒なら安全で効率的に解決できます。技術的な実装は僕たちに任せて、皆さんは「何を解決したいか」に集中してください。明日からの業務が、きっとより効率的で価値創造的なものになるはずです。何か新しい課題を見つけたら、いつでも声をかけてくださいね!開発で使用したツール・技術Cursor:AIペアプログラミングツールPython Flask:Webアプリケーションフレームワークpydub + FFmpeg:音声処理ライブラリpython-magic:ファイル形式検証仮想環境(venv):プロジェクト環境分離HTML/CSS/JavaScript:モダンなユーザーインターフェース開発期間と効果開発時間:初回システム構築 数時間、セキュリティ強化 1時間程度業務効率化:90%以上の時間短縮技術習得:仮想環境とセキュリティ設計の理解継続的価値:AI文字起こし前処理の完全自動化#ライターの紹介-横内 圭介(Musubi Inc.):調査・分析、戦略〜施策の立案と実行まで担当略歴 ##略歴"""-総合商社にて、主に製造業を中心としたマーケティング・営業を担当。15年以上に亘り、国内外メーカーの海外進出支援や営業・マーケティング戦略の立案から実行までを行う。2015年にMusubi Inc.を設立してから全く畑の違うブランディングの業務に従事。製造、建設、サービス、銀行、飲食、ホテル、運送、流通、リサイクルなど多くの業界を担当し、様々な領域の課題可決をコンサルタントとして担当している。ここ1年ほど様々なAIツールに触れ自身の業務効率が格段に上がったことから、兼業でブランディングやマーケティング業務を担われている方などに向けて情報発信できたらなと考えています。兼業でなかなか時間が割けない=ブランディング・マーケティング活動ができないといった方々に少しでも役に立てればと思っています。"""