import os import gradio as gr from openai import OpenAI from yt_dlp import YoutubeDL from pydub import AudioSegment import math # 定数 MAX_LENGTH = 5000 MODEL_SUMMARY = "gpt-3.5-turbo-0125" # 分割時間設定(20分) split_time = 20 * 60 * 1000 lang_code = {'Japanese': "ja", 'English': "en"} def set_state(openai_key, lang, state): """ 設定タブの情報をセッションに保存する関数 """ state["openai_key"]= openai_key state["lang"] = lang_code[lang] 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 else: file_name = file # 音声ファイルを分割 audio_list = audio_seg(file_name) # 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 = file_name.replace(".mp3",".txt") combin_text(text_list, text_name) return text_name, err_msg 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") # ファイル名設定 text_name = audio.replace(".mp3","_.txt") with open(text_name, mode="w") as f: # テキストに書き出す f.write(trans_text) text_list.append(text_name) return text_list except Exception as e: return None def audio_seg(file_name): # 分割したリスト div_file = [] # ファイルから音声情報取得 audio = AudioSegment.from_mp3(file_name) # 音声の長さ取得(ミリ秒) 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): print(file) err_msg = "" # OpenAIキーチェック if state["openai_key"] == "": err_msg = "OpenAIキーを入力してください。(設定タブ)" return None, err_msg # URL入力チェック 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, file) if err_msg != "": return file, 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, 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_SUMMARY, 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 = "