import os import gradio as gr from openai import OpenAI from yt_dlp import YoutubeDL from pydub import AudioSegment import math # 定数 MAX_LENGTH = 50000 # MODEL_SUMMARY = "gpt-3.5-turbo-0125" gpt_model = ["gpt-4o", "gpt-3.5-turbo-0125"] gpt_model_df = "gpt-4o" # 分割時間設定(20分) split_time = 20 * 60 * 1000 lang_code = {'Japanese': "ja", 'English': "en"} def set_state(openai_key, lang, model_sum, state): """ 設定タブの情報をセッションに保存する関数 """ state["openai_key"]= openai_key state["lang"] = lang_code[lang] state["model_sum"] = model_sum return state def youtube_mp3(url): # ファイル名は動画のIDに mp3_name = url[url.rfind('/') + 1:].replace("watch?v=","") # フォーマット設定 ydl_opts = { 'outtmpl': mp3_name, "format": "mp3/bestaudio/best", "postprocessors": [ { "key": "FFmpegExtractAudio", "preferredcodec": "mp3", } ], } try : # yt-dlpでmp3に with YoutubeDL(ydl_opts) as ydl: result = ydl.download([url]) return mp3_name + ".mp3" except Exception as e: print(e) return None def create_textfile(url, file, state): err_msg = "" # OpenAIキーチェック if state["openai_key"] == "": err_msg = "OpenAIキーを入力してください。(設定タブ)" return None, err_msg # URL入力チェック if url == "" and file is None: err_msg = "URLを入力するか、音声ファイルをアップして下さい。" return None, err_msg # OpenAIクライアント作成 os.environ["OPENAI_API_KEY"] = state["openai_key"] client = OpenAI() # client作成後は消す os.environ["OPENAI_API_KEY"] = "" # 動画を音声ファイルにする if url != "": file_name = youtube_mp3(url) if file_name is None: err_msg = "音声ファイルにする作業でエラーが発生しました。URLを確認して下さい。" return None, err_msg # ファイルを絶対パスに file_path = os.getcwd() + "/" + file_name else: # ファイル名のみ取得 file_name = os.path.basename(file) # ファイルを移動 file_path = os.getcwd() + "/" + file_name os.replace(file, file_path) # 音声ファイルを分割 audio_list = audio_seg(file_path) # whisperで文字に起こす text_list = whisper_audio(client, audio_list, state["lang"]) if text_list is None: err_msg = "whisperでエラーが発生しました。OpenAI APIキーが正しいか、クレジット残高があるか確認して下さい。" return None, err_msg text_name = rename_audio(file_name) # text_name = file_name.replace(".mp3",".txt") # テキストファイルを結合 if len(text_list) > 1: combin_text(text_list, text_name) return text_name, err_msg def rename_audio(audio_name): text_name = "" if ".mp3" in audio_name: text_name = audio_name.replace(".mp3",".txt") elif ".MP3" in audio_name: text_name = audio_name.replace(".MP3",".txt") elif ".wav" in audio_name: text_name = audio_name.replace(".wav",".txt") elif ".WAV" in audio_name: text_name = audio_name.replace(".WAV",".txt") if text_name == "": text_name = audio_name return text_name def whisper_audio(client, audio_list, lang): text_list = [] try: for audio in audio_list: audio_file= open(audio, "rb") trans_text = client.audio.transcriptions.create(model="whisper-1", file=audio_file, language=lang, response_format="text") # print(audio) text_name = rename_audio(audio) # print(text_name) with open(text_name, mode="w") as f: # テキストに書き出す f.write(trans_text) text_list.append(text_name) return text_list except Exception as e: print(e) return None def audio_seg(file_path): # 分割したリスト div_file = [] # ファイル名取得 file_name = os.path.basename(file_path) # ファイルから音声情報取得 audio = AudioSegment.from_mp3(file_path) # 音声の長さ取得(ミリ秒) dur_mlseconds = audio.duration_seconds * 1000 # 分割数を決める div_count = math.ceil(dur_mlseconds / split_time) if div_count == 1: # 分割なしの時は元ファイルのみ div_file.append(file_name) return div_file # 分割時間初期設定 start = 0 end = split_time for i in range(div_count): div_audio = audio[start:end] div_audio.export(str(i+1) + "_" + file_name, format="mp3") # ファイル名をセット div_file.append(str(i+1) + "_" + file_name) start = end end += split_time return div_file def combin_text(text_list, text_name): # ファイルを一つにまとめる with open(text_name, "w") as of: for file in text_list: with open(file, "r") as f: of.write(f.read()) # 必要であれば改行を加える # outfile.write(infile.read() + "\n") return def create_mp3(url, state): err_msg = "" # URL入力チェック if url == "": err_msg = "URLを入力して下さい。" return None, err_msg # 動画を音声ファイルにする file_name = youtube_mp3(url) if file_name is None: err_msg = "音声ファイルにする作業でエラーが発生しました。URLを確認して下さい。" return None, err_msg return file_name, "" def create_summary(file, state): err_msg = "" # OpenAIキーチェック if state["openai_key"] == "": err_msg = "OpenAIキーを入力してください。(設定タブ)" return None, err_msg # ファイルチェック if file is None: err_msg = "テキストファイルがありません。" return None, err_msg # OpenAIクライアント作成 os.environ["OPENAI_API_KEY"] = state["openai_key"] client = OpenAI() # client作成後は消す os.environ["OPENAI_API_KEY"] = "" summary, err_msg = exec_summary(client, state["model_sum"], file) if err_msg != "": return None, err_msg sum_file = "summary_" + os.path.basename(file) with open(sum_file, mode="w") as f: f.write(summary) return sum_file, "" def exec_summary(client, model_sum, file): try: with open(file, 'r') as f: text = f.read() if len(text) > MAX_LENGTH: err_msg = "要約の文字数上限を超えています。" return "", err_msg messages=[ {"role": "system", "content": "あなたは優秀なアシスタントです。与えられた文章を要約して下さい。"}, {"role": "user", "content": text}, ] # GPTに問い合わせ response = client.chat.completions.create( model=model_sum, messages=messages, # max_tokens=MAX_TOKENS, ) summary = response.choices[0].message.content return summary, "" except Exception as e: print(e) return "", "要約作成でエラーが発生しました。" with gr.Blocks() as demo: title = "