Spaces:
Running
Running
merge fixTranscription
Browse files- __pycache__/analyze.cpython-310.pyc +0 -0
- __pycache__/process.cpython-310.pyc +0 -0
- __pycache__/transcription.cpython-310.pyc +0 -0
- app.py +13 -6
- process.py +15 -10
- templates/talkDetail.html +6 -2
- transcription.py +18 -6
__pycache__/analyze.cpython-310.pyc
CHANGED
Binary files a/__pycache__/analyze.cpython-310.pyc and b/__pycache__/analyze.cpython-310.pyc differ
|
|
__pycache__/process.cpython-310.pyc
CHANGED
Binary files a/__pycache__/process.cpython-310.pyc and b/__pycache__/process.cpython-310.pyc differ
|
|
__pycache__/transcription.cpython-310.pyc
CHANGED
Binary files a/__pycache__/transcription.cpython-310.pyc and b/__pycache__/transcription.cpython-310.pyc differ
|
|
app.py
CHANGED
@@ -13,13 +13,13 @@ transcripter = TranscriptionMaker()
|
|
13 |
app = Flask(__name__)
|
14 |
|
15 |
users = []
|
16 |
-
segments_dir = ""
|
17 |
transcription_text=""
|
18 |
harassment_keywords = [
|
19 |
"バカ", "馬鹿", "アホ", "死ね", "クソ", "うざい",
|
20 |
"きもい", "キモい", "ブス", "デブ", "ハゲ",
|
21 |
"セクハラ", "パワハラ", "モラハラ"
|
22 |
]
|
|
|
23 |
|
24 |
# トップページ(テンプレート: index.html)
|
25 |
@app.route('/')
|
@@ -32,7 +32,6 @@ def index():
|
|
32 |
def feedback():
|
33 |
return render_template('feedback.html')
|
34 |
|
35 |
-
|
36 |
# 会話詳細画面(テンプレート: talkDetail.html)
|
37 |
@app.route('/talk_detail', methods=['GET', 'POST'])
|
38 |
def talk_detail():
|
@@ -53,12 +52,15 @@ def confirm():
|
|
53 |
def reset_html():
|
54 |
return render_template('reset.html')
|
55 |
|
56 |
-
|
57 |
@app.route('/reset_member', methods=['GET', 'POST'])
|
58 |
def reset_member():
|
59 |
global users # ←これを追加!
|
60 |
#data = request.get_json()
|
61 |
#name = data['name'] # 名前を取得
|
|
|
|
|
|
|
62 |
base_audio_dir = "/tmp/data/base_audio"
|
63 |
for name in users:
|
64 |
file_path = os.path.join(base_audio_dir, f"{name}.wav")
|
@@ -76,10 +78,11 @@ def reset_member():
|
|
76 |
# 書き起こし作成エンドポイント
|
77 |
@app.route('/transcription',methods =['GET','POST'])
|
78 |
def transcription():
|
79 |
-
global segments_dir
|
80 |
global transcription_text
|
|
|
|
|
81 |
try:
|
82 |
-
transcription_text = transcripter.create_transcription(
|
83 |
print(transcription_text)
|
84 |
with open(transcription_text,'r',encoding='utf-8') as file:
|
85 |
file_content = file.read()
|
@@ -123,7 +126,7 @@ def analyze():
|
|
123 |
# 音声アップロード&解析エンドポイント
|
124 |
@app.route('/upload_audio', methods=['POST'])
|
125 |
def upload_audio():
|
126 |
-
global
|
127 |
try:
|
128 |
data = request.get_json()
|
129 |
# name か users のいずれかが必須。どちらも無い場合はエラー
|
@@ -153,23 +156,27 @@ def upload_audio():
|
|
153 |
if len(users) > 1:
|
154 |
print("複数人の場合の処理")
|
155 |
matched_times, segments_dir = process.process_multi_audio(reference_paths, audio_path, threshold=0.05)
|
|
|
156 |
# 各メンバーのrateを計算
|
157 |
total_time = sum(matched_times)
|
158 |
rates = [(time / total_time) * 100 if total_time > 0 else 0 for time in matched_times]
|
159 |
return jsonify({"rates": rates}), 200
|
160 |
else:
|
161 |
matched_time, unmatched_time, segments_dir = process.process_audio(reference_paths[0], audio_path, threshold=0.05)
|
|
|
162 |
total_time = matched_time + unmatched_time
|
163 |
rate = (matched_time / total_time) * 100 if total_time > 0 else 0
|
164 |
return jsonify({"rate": rate}), 200
|
165 |
except Exception as e:
|
166 |
print("Error in /upload_audio:", str(e))
|
167 |
return jsonify({"error": "サーバーエラー", "details": str(e)}), 500
|
|
|
168 |
@app.route('/reset', methods=['GET'])
|
169 |
def reset():
|
170 |
global users
|
171 |
users=[]
|
172 |
return 200
|
|
|
173 |
@app.route('/upload_base_audio', methods=['POST'])
|
174 |
def upload_base_audio():
|
175 |
global users#グローバル変数を編集できるようにする
|
|
|
13 |
app = Flask(__name__)
|
14 |
|
15 |
users = []
|
|
|
16 |
transcription_text=""
|
17 |
harassment_keywords = [
|
18 |
"バカ", "馬鹿", "アホ", "死ね", "クソ", "うざい",
|
19 |
"きもい", "キモい", "ブス", "デブ", "ハゲ",
|
20 |
"セクハラ", "パワハラ", "モラハラ"
|
21 |
]
|
22 |
+
total_audio = ""
|
23 |
|
24 |
# トップページ(テンプレート: index.html)
|
25 |
@app.route('/')
|
|
|
32 |
def feedback():
|
33 |
return render_template('feedback.html')
|
34 |
|
|
|
35 |
# 会話詳細画面(テンプレート: talkDetail.html)
|
36 |
@app.route('/talk_detail', methods=['GET', 'POST'])
|
37 |
def talk_detail():
|
|
|
52 |
def reset_html():
|
53 |
return render_template('reset.html')
|
54 |
|
55 |
+
#メンバー削除&累積音声削除
|
56 |
@app.route('/reset_member', methods=['GET', 'POST'])
|
57 |
def reset_member():
|
58 |
global users # ←これを追加!
|
59 |
#data = request.get_json()
|
60 |
#name = data['name'] # 名前を取得
|
61 |
+
global total_audio
|
62 |
+
print(total_audio)
|
63 |
+
process.delete_files_in_directory(total_audio)
|
64 |
base_audio_dir = "/tmp/data/base_audio"
|
65 |
for name in users:
|
66 |
file_path = os.path.join(base_audio_dir, f"{name}.wav")
|
|
|
78 |
# 書き起こし作成エンドポイント
|
79 |
@app.route('/transcription',methods =['GET','POST'])
|
80 |
def transcription():
|
|
|
81 |
global transcription_text
|
82 |
+
global total_audio
|
83 |
+
print(total_audio)
|
84 |
try:
|
85 |
+
transcription_text = transcripter.create_transcription(total_audio)
|
86 |
print(transcription_text)
|
87 |
with open(transcription_text,'r',encoding='utf-8') as file:
|
88 |
file_content = file.read()
|
|
|
126 |
# 音声アップロード&解析エンドポイント
|
127 |
@app.route('/upload_audio', methods=['POST'])
|
128 |
def upload_audio():
|
129 |
+
global total_audio
|
130 |
try:
|
131 |
data = request.get_json()
|
132 |
# name か users のいずれかが必須。どちらも無い場合はエラー
|
|
|
156 |
if len(users) > 1:
|
157 |
print("複数人の場合の処理")
|
158 |
matched_times, segments_dir = process.process_multi_audio(reference_paths, audio_path, threshold=0.05)
|
159 |
+
total_audio = transcripter.merge_segments(segments_dir)
|
160 |
# 各メンバーのrateを計算
|
161 |
total_time = sum(matched_times)
|
162 |
rates = [(time / total_time) * 100 if total_time > 0 else 0 for time in matched_times]
|
163 |
return jsonify({"rates": rates}), 200
|
164 |
else:
|
165 |
matched_time, unmatched_time, segments_dir = process.process_audio(reference_paths[0], audio_path, threshold=0.05)
|
166 |
+
total_audio = transcripter.merge_segments(segments_dir)
|
167 |
total_time = matched_time + unmatched_time
|
168 |
rate = (matched_time / total_time) * 100 if total_time > 0 else 0
|
169 |
return jsonify({"rate": rate}), 200
|
170 |
except Exception as e:
|
171 |
print("Error in /upload_audio:", str(e))
|
172 |
return jsonify({"error": "サーバーエラー", "details": str(e)}), 500
|
173 |
+
|
174 |
@app.route('/reset', methods=['GET'])
|
175 |
def reset():
|
176 |
global users
|
177 |
users=[]
|
178 |
return 200
|
179 |
+
|
180 |
@app.route('/upload_base_audio', methods=['POST'])
|
181 |
def upload_base_audio():
|
182 |
global users#グローバル変数を編集できるようにする
|
process.py
CHANGED
@@ -58,15 +58,7 @@ class AudioProcessor():
|
|
58 |
embedding2 = self.inference(path2)
|
59 |
return float(self.cosine_similarity(embedding1.data.flatten(), embedding2.data.flatten()))
|
60 |
|
61 |
-
|
62 |
-
letters = string.ascii_letters + string.digits
|
63 |
-
return ''.join(random.choice(letters) for i in range(length))
|
64 |
-
|
65 |
-
def generate_filename(self,random_length):
|
66 |
-
random_string = self.generate_random_string(random_length)
|
67 |
-
current_time = datetime.now().strftime("%Y%m%d%H%M%S")
|
68 |
-
filename = f"{current_time}_{random_string}.wav"
|
69 |
-
return filename
|
70 |
|
71 |
def process_audio(self, reference_path, input_path, output_folder='/tmp/data/matched_segments', seg_duration=1.0, threshold=0.5):
|
72 |
# 出力先ディレクトリの中身をクリアする
|
@@ -182,4 +174,17 @@ class AudioProcessor():
|
|
182 |
print(f"File Not Found Error: {e}")
|
183 |
except Exception as e:
|
184 |
print(f"Unexpected Error: {e}")
|
185 |
-
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
embedding2 = self.inference(path2)
|
59 |
return float(self.cosine_similarity(embedding1.data.flatten(), embedding2.data.flatten()))
|
60 |
|
61 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
|
63 |
def process_audio(self, reference_path, input_path, output_folder='/tmp/data/matched_segments', seg_duration=1.0, threshold=0.5):
|
64 |
# 出力先ディレクトリの中身をクリアする
|
|
|
174 |
print(f"File Not Found Error: {e}")
|
175 |
except Exception as e:
|
176 |
print(f"Unexpected Error: {e}")
|
177 |
+
return None
|
178 |
+
|
179 |
+
def delete_files_in_directory(self,directory_path):
|
180 |
+
try:
|
181 |
+
# ディレクトリ内のすべてのファイルを取得
|
182 |
+
for filename in os.listdir(directory_path):
|
183 |
+
file_path = os.path.join(directory_path, filename)
|
184 |
+
# ファイルのみ削除する
|
185 |
+
if os.path.isfile(file_path):
|
186 |
+
os.remove(file_path)
|
187 |
+
print(f"{file_path} を削除しました")
|
188 |
+
except Exception as e:
|
189 |
+
print(f"エラーが発生しました: {e}")
|
190 |
+
|
templates/talkDetail.html
CHANGED
@@ -43,17 +43,21 @@
|
|
43 |
if (!response.ok) throw new Error("データ取得に失敗しました。");
|
44 |
|
45 |
const data = await response.json();
|
46 |
-
const conversations = data.
|
47 |
|
48 |
-
if (!
|
49 |
throw new Error("会話データが見つかりませんでした。");
|
50 |
}
|
|
|
51 |
const formattedText = conversations
|
52 |
|
53 |
.map((conv) => `【${conv.speaker}】 ${conv.text}`)
|
54 |
.join("\n");
|
55 |
console.log("フォーマットテキスト:", formattedText);
|
56 |
transcriptionElement.textContent = formattedText;
|
|
|
|
|
|
|
57 |
} catch (error) {
|
58 |
transcriptionElement.textContent = `エラー: ${error.message}`;
|
59 |
console.error("データ取得エラー:", error);
|
|
|
43 |
if (!response.ok) throw new Error("データ取得に失敗しました。");
|
44 |
|
45 |
const data = await response.json();
|
46 |
+
const conversations = data.transcription;
|
47 |
|
48 |
+
if (!data || !data.transcription) {
|
49 |
throw new Error("会話データが見つかりませんでした。");
|
50 |
}
|
51 |
+
/*
|
52 |
const formattedText = conversations
|
53 |
|
54 |
.map((conv) => `【${conv.speaker}】 ${conv.text}`)
|
55 |
.join("\n");
|
56 |
console.log("フォーマットテキスト:", formattedText);
|
57 |
transcriptionElement.textContent = formattedText;
|
58 |
+
*/
|
59 |
+
transcriptionElement.textContent = conversations;
|
60 |
+
console.log(conversations);
|
61 |
} catch (error) {
|
62 |
transcriptionElement.textContent = `エラー: ${error.message}`;
|
63 |
console.error("データ取得エラー:", error);
|
transcription.py
CHANGED
@@ -1,6 +1,9 @@
|
|
1 |
import os
|
2 |
from faster_whisper import WhisperModel
|
3 |
from pydub import AudioSegment
|
|
|
|
|
|
|
4 |
|
5 |
# Matplotlibのキャッシュディレクトリを変更
|
6 |
os.environ["MPLCONFIGDIR"] = "/tmp/matplotlib"
|
@@ -18,10 +21,9 @@ class TranscriptionMaker():
|
|
18 |
|
19 |
|
20 |
#音声ファイルのディレクトリを受け取り、書き起こしファイルを作成する
|
21 |
-
def create_transcription(self,
|
22 |
results = []
|
23 |
-
|
24 |
-
audio_directory = self.merge_segments(segments_directory)
|
25 |
#ディレクトリ内のファイルを全て取得
|
26 |
if not os.path.isdir(audio_directory):
|
27 |
raise ValueError(f"The specified path is not a valid directory: {audio_directory}")
|
@@ -53,7 +55,7 @@ class TranscriptionMaker():
|
|
53 |
return output_file
|
54 |
|
55 |
#ファイル名が連続しているならくっつける
|
56 |
-
def merge_segments(self,segments_dir,output_dir = "/tmp/data/
|
57 |
if not os.path.exists(output_dir):
|
58 |
os.makedirs(output_dir, exist_ok=True)
|
59 |
|
@@ -90,7 +92,17 @@ class TranscriptionMaker():
|
|
90 |
segment = AudioSegment.from_file(file_path)
|
91 |
combined_audio += segment
|
92 |
# 出力ファイル名を設定して保存
|
93 |
-
output_file = os.path.join(output_dir,
|
94 |
combined_audio.export(output_file, format='wav')
|
95 |
|
96 |
-
return output_dir
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import os
|
2 |
from faster_whisper import WhisperModel
|
3 |
from pydub import AudioSegment
|
4 |
+
import string
|
5 |
+
import random
|
6 |
+
from datetime import datetime
|
7 |
|
8 |
# Matplotlibのキャッシュディレクトリを変更
|
9 |
os.environ["MPLCONFIGDIR"] = "/tmp/matplotlib"
|
|
|
21 |
|
22 |
|
23 |
#音声ファイルのディレクトリを受け取り、書き起こしファイルを作成する
|
24 |
+
def create_transcription(self,audio_directory):
|
25 |
results = []
|
26 |
+
|
|
|
27 |
#ディレクトリ内のファイルを全て取得
|
28 |
if not os.path.isdir(audio_directory):
|
29 |
raise ValueError(f"The specified path is not a valid directory: {audio_directory}")
|
|
|
55 |
return output_file
|
56 |
|
57 |
#ファイル名が連続しているならくっつける
|
58 |
+
def merge_segments(self,segments_dir,output_dir = "/tmp/data/merged_segment"):
|
59 |
if not os.path.exists(output_dir):
|
60 |
os.makedirs(output_dir, exist_ok=True)
|
61 |
|
|
|
92 |
segment = AudioSegment.from_file(file_path)
|
93 |
combined_audio += segment
|
94 |
# 出力ファイル名を設定して保存
|
95 |
+
output_file = os.path.join(output_dir, self.generate_filename(3))
|
96 |
combined_audio.export(output_file, format='wav')
|
97 |
|
98 |
+
return output_dir
|
99 |
+
|
100 |
+
def generate_random_string(self,length):
|
101 |
+
letters = string.ascii_letters + string.digits
|
102 |
+
return ''.join(random.choice(letters) for i in range(length))
|
103 |
+
|
104 |
+
def generate_filename(self,random_length):
|
105 |
+
random_string = self.generate_random_string(random_length)
|
106 |
+
current_time = datetime.now().strftime("%Y%m%d%H%M%S")
|
107 |
+
filename = f"{current_time}_{random_string}.wav"
|
108 |
+
return filename
|