# [メタ情報] # 識別子: 字幕かんたんエディタappの作成_exe # 補足: # [/メタ情報] 要約: 「字幕かんたんエディタ」は、macOS向けのVTT字幕作成・編集アプリケーションです。Python (`subtitle_easy_editor.py`, `vtt_parser_logic.py`) とHTML/JavaScript (`html/index.html`) で構成され、PyInstallerとcreate-dmgスクリプト (`build_dmg.sh`, `subtitle_easy_editor.spec`) を用いて`SubtitleEasyEditor.dmg`としてビルドされます。ビルド後、DMGと`readme.txt`をZIPにまとめ配布します。 本アプリは、ユーザーが選択した動画・音声ファイルと連携し、WaveSurfer.jsによる波形表示を介して字幕の開始・終了時刻やテキストを直感的に編集・追加できます。既存VTTの読み込みや新規作成に対応し、保存時には字幕一覧表示用のHTMLファイル(`_listJ.txt`)を自動生成する機能も持ちます。 初回起動時はmacOSのセキュリティにより「右クリック」→「開く」が必要です。以降はFinderから動画・音声ファイルをアプリで開くことで、エディタ画面が起動し、字幕作成・編集作業を開始できます。 subtitle_pkgフォルダの中身: subtitle_easy_editor.py readme.txt build_dmg.sh html/index.html subtitle_easy_editor.spec vtt_parser_logic.py ターミナルで以下を入力して、アプリのビルドをする pkill -f "subtitle_easy_editor" cd ~/Desktop/subtitle_pkg source venv/bin/activate bash build_dmg.sh ビルドが成功すると、 subtitle_pkgフォルダの中に、 SubtitleEasyEditor.dmg が生成される。 SubtitleEasyEditor_distフォルダを作り SubtitleEasyEditor.dmg readme.txt を入れて、 SubtitleEasyEditor_dist.zip を作り配布する。 subtitle_easy_editor.py ``` #!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import sys import threading import socket import bottle import webview from vtt_parser_logic import generate_list_j def get_resource_path(relative_path): try: base_path = sys._MEIPASS except Exception: base_path = os.path.abspath(".") return os.path.join(base_path, relative_path) class SubtitleAPI: def __init__(self): self.window = None self.current_media_path = None self.current_vtt_path = None self.media_port = None def get_media_url(self): if self.current_media_path and os.path.exists(self.current_media_path): return f"http://127.0.0.1:{self.media_port}/stream" return "" def get_vtt_content(self): if self.current_vtt_path and os.path.exists(self.current_vtt_path): try: with open(self.current_vtt_path, 'r', encoding='utf-8') as f: return f.read() except Exception as e: return str(e) return "" def select_existing_vtt(self): try: file_types = ('VTT Files (*.vtt;*.txt)', 'All Files (*.*)') result = self.window.create_file_dialog( webview.OPEN_DIALOG, allow_multiple=False, file_types=file_types ) if result and len(result) > 0: file_path = result[0] self.current_vtt_path = file_path # ★追加対策:_listJ.txt が存在しない初期状態の場合、開いた瞬間に自動生成する dir_name = os.path.dirname(file_path) base_name = os.path.splitext(os.path.basename(file_path))[0] list_j_path = os.path.join(dir_name, f"{base_name}_listJ.txt") if not os.path.exists(list_j_path): generate_list_j(file_path) return {"status": "success", "path": file_path, "filename": os.path.basename(file_path)} return {"status": "cancel"} except Exception as e: return {"status": "error", "message": str(e)} def create_new_vtt(self): try: file_types = ('VTT Files (*.vtt)', 'All Files (*.*)') result = self.window.create_file_dialog( webview.SAVE_DIALOG, save_filename='new_subtitle.vtt', file_types=file_types ) if result: file_path = result[0] if isinstance(result, (tuple, list)) else result if not file_path.lower().endswith('.vtt'): file_path += '.vtt' with open(file_path, 'w', encoding='utf-8') as f: f.write("WEBVTT\n\n") self.current_vtt_path = file_path # ★新規作成時も同様に空の _listJ.txt を用意しておく generate_list_j(file_path) return {"status": "success", "path": file_path, "filename": os.path.basename(file_path)} return {"status": "cancel"} except Exception as e: return {"status": "error", "message": str(e)} def save_subtitle_and_generate_list(self, vtt_content): if not self.current_vtt_path: return {"status": "error", "message": "VTTファイルが指定されていません。"} try: with open(self.current_vtt_path, 'w', encoding='utf-8') as f: f.write(vtt_content) success = generate_list_j(self.current_vtt_path) if success: return {"status": "success", "message": "VTT及び_listJ.txtを保存完了しました。"} else: return {"status": "partial_success", "message": "VTTは保存されましたが、リスト生成に失敗しました。"} except Exception as e: return {"status": "error", "message": str(e)} api = SubtitleAPI() media_app = bottle.Bottle() @media_app.hook('after_request') def enable_cors(): bottle.response.headers['Access-Control-Allow-Origin'] = '*' bottle.response.headers['Access-Control-Allow-Methods'] = 'GET, OPTIONS, HEAD' bottle.response.headers['Access-Control-Allow-Headers'] = 'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token, Range' bottle.response.headers['Access-Control-Expose-Headers'] = 'Content-Range, Accept-Ranges, Content-Length' @media_app.route('/stream', method=['GET', 'OPTIONS']) def serve_stream(): if bottle.request.method == 'OPTIONS': return {} path = api.current_media_path if not path or not os.path.exists(path): return bottle.HTTPError(404, "File not found") return bottle.static_file(os.path.basename(path), root=os.path.dirname(path)) def get_free_port(): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind(('127.0.0.1', 0)) return s.getsockname()[1] def start_media_server(port): bottle.run(app=media_app, host='127.0.0.1', port=port, quiet=True) def main(): media_path = sys.argv[1] if len(sys.argv) > 1 else None api.current_media_path = media_path port = get_free_port() api.media_port = port server_thread = threading.Thread(target=start_media_server, args=(port,), daemon=True) server_thread.start() html_path = get_resource_path(os.path.join("html", "index.html")) with open(html_path, 'r', encoding='utf-8') as f: html_content = f.read() window = webview.create_window( title="字幕かんたんエディタ", html=html_content, js_api=api, width=600, height=850, resizable=True ) api.window = window webview.start(debug=False) if __name__ == "__main__": main() ``` readme.txt ``` ====================================================== 【はじめにお読みください】字幕かんたんエディタ 導入ガイド ====================================================== この度は「字幕かんたんエディタ」をダウンロードいただきありがとうございます。 macOSの仕様上、初回起動時のみ簡単なセキュリティ確認が必要となります。 システム設定を変更することなく、以下の3ステップで簡単にご利用いただけます。 【導入手順(初回のみ)】 1. アプリのインストール このフォルダに入っている「字幕かんたんエディタ」のアイコンを、 右隣の「Applications」フォルダへドラッグ&ドロップしてください。 (これでインストールは完了です) 2. 魔法の「右クリック」起動 アプリケーションフォルダを開き、「字幕かんたんエディタ」のアイコンを 【右クリック(またはControlキーを押しながらクリック)】し、 メニューから「開く」を選択してください。 3. 「開く」ボタンを押す 「開発元を検証できないため開けません」という警告画面が出ますが、 その中にある「開く」ボタンをクリックしてください。 ※次回からは、通常通りダブルクリックで起動できるようになります! 【便利な使い方(日常の作業フロー)】 インストール後は、以下の手順でスムーズに字幕作成を開始できます。 1. MacのFinderで、編集したい動画や音声ファイルを「右クリック」します。 2. メニューの「このアプリケーションで開く」の中から、「字幕かんたんエディタ.app」を選びます。 (※Macの環境によっては「サービス」や「クイックアクション」の中に表示される場合もあります) 3. アプリが起動したら、メニュー画面から「既存のVTTファイルを指定」または「新規にVTTファイルを作成」を選択してください。 4. 選択した動画・音声ファイルが自動的に読み込まれた状態で、エディタ画面が開きます。 ====================================================== ``` build_dmg.sh ``` #!/bin/bash APP_NAME="字幕かんたんエディタ.app" APP_PATH="dist/${APP_NAME}" DMG_NAME="SubtitleEasyEditor.dmg" echo "PyInstallerでビルドしています..." pyinstaller subtitle_easy_editor.spec --clean if [ ! -d "$APP_PATH" ]; then echo "エラー: ${APP_PATH} のビルドに失敗しました。" exit 1 fi rm -f "$DMG_NAME" echo "DMGパッケージを作成しています..." create-dmg \ --volname "字幕かんたんエディタ インストーラ" \ --window-pos 200 120 \ --window-size 600 400 \ --icon-size 100 \ --icon "$APP_NAME" 150 190 \ --hide-extension "$APP_NAME" \ --app-drop-link 450 190 \ "$DMG_NAME" \ "dist/" if [ $? -eq 0 ]; then echo "✅ DMGの作成が完了しました: $DMG_NAME" else echo "❌ DMGの作成に失敗しました。" fi ``` html/index.html ```
\n' footer_html = '