Update app.py
Browse files
app.py
CHANGED
@@ -16,7 +16,7 @@ st.set_page_config(layout="wide")
|
|
16 |
st.title("VOD μ±ν
ν¬λ‘€λ¬")
|
17 |
st.write("VOD URLμ μ
λ ₯νκ³ μ±ν
λ°μ΄ν°λ₯Ό ν¬λ‘€λ§ν©λλ€.")
|
18 |
|
19 |
-
# URL μ
λ ₯ λ°κΈ°
|
20 |
vod_url = st.text_input("VOD URL μ
λ ₯")
|
21 |
|
22 |
# μ νλ μκ°λλ₯Ό μ μ₯ν 곡κ°
|
@@ -25,7 +25,7 @@ if 'selected_times' not in st.session_state:
|
|
25 |
|
26 |
# μ±ν
ν¬λ‘€λ§ ν¨μ
|
27 |
def crawl_chats(vod_url):
|
28 |
-
# URL μ€μ
|
29 |
url = vod_url + "/chats"
|
30 |
|
31 |
# μμ² ν€λ (νμμ μΏ ν€λ κΈ°ν ν€λ μ 보 μΆκ°)
|
@@ -47,11 +47,10 @@ def crawl_chats(vod_url):
|
|
47 |
chat_counts = defaultdict(int)
|
48 |
laugh_counts = defaultdict(int)
|
49 |
total_chats_collected = 0 # μ΄ μμ§λ μ±ν
κ°μ
|
|
|
50 |
|
51 |
# μ±ν
λ°μ΄ν°λ₯Ό μμ°¨μ μΌλ‘ μμ²νμ¬ κ°μ Έμ€κΈ°
|
52 |
status_text = st.empty() # μν λ©μμ§ μΆλ ₯μ©
|
53 |
-
start_time = time.time() # ν¬λ‘€λ§ μμ μκ°
|
54 |
-
|
55 |
while True:
|
56 |
# API μμ² λ³΄λ΄κΈ°
|
57 |
response = requests.get(url, params=params, headers=headers)
|
@@ -105,9 +104,7 @@ def crawl_chats(vod_url):
|
|
105 |
laugh_counts[minute_key] += 1
|
106 |
|
107 |
total_chats_collected += len(chats)
|
108 |
-
|
109 |
-
# νμ¬ μκ°κ³Ό κ²½κ³Ό μκ° νμ
|
110 |
-
elapsed_time = time.time() - start_time
|
111 |
status_text.text(f"νμ¬κΉμ§ μμ§λ μ±ν
λ©μμ§ κ°μ: {total_chats_collected} | κ²½κ³Ό μκ°: {int(elapsed_time // 60)}λΆ {int(elapsed_time % 60)}μ΄")
|
112 |
|
113 |
# λ€μ μμ²μ μν΄ playerMessageTime νλΌλ―Έν° μ
λ°μ΄νΈ
|
@@ -118,6 +115,39 @@ def crawl_chats(vod_url):
|
|
118 |
|
119 |
return "\n".join(chat_logs), chat_counts, laugh_counts
|
120 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
# λ²νΌμ λλ μ λ μ±ν
ν¬λ‘€λ§ μμ
|
122 |
if 'chat_logs' not in st.session_state:
|
123 |
st.session_state['chat_logs'] = None
|
@@ -186,6 +216,7 @@ if st.session_state['chat_logs']:
|
|
186 |
title="λΆλΉ μ±ν
λ° γ
γ
γ
γ
μ±ν
κ°μ",
|
187 |
xaxis_title="μκ°",
|
188 |
yaxis_title="μ±ν
κ°μ",
|
|
|
189 |
xaxis=dict(showticklabels=False), # xμΆ μκ° λ μ΄λΈ μ¨κΉ
|
190 |
hovermode="x unified", # λ§μ°μ€λ₯Ό μ¬λ Έμ λ ν΄λΉ xμΆμμ ν΄ν νμ
|
191 |
showlegend=True,
|
@@ -213,35 +244,7 @@ if st.session_state['chat_logs']:
|
|
213 |
minute = 0
|
214 |
|
215 |
# μ νλ μκ°λλ₯Ό νμ λ° μμ κΈ°λ₯
|
216 |
-
|
217 |
-
st.write("### μ νλ μκ°λ")
|
218 |
-
for time in st.session_state['selected_times']:
|
219 |
-
col1, col2 = st.columns([9, 1])
|
220 |
-
col1.write(f"{time}")
|
221 |
-
if col2.button("X", key=f"remove_{time}"):
|
222 |
-
st.session_state['selected_times'].remove(time)
|
223 |
-
|
224 |
-
# yt-dlpλ₯Ό μ¬μ©νμ¬ μ νλ μκ°λμ μμμ λ€μ΄λ‘λ
|
225 |
-
def download_clips():
|
226 |
-
if st.session_state['selected_times']:
|
227 |
-
for idx, start_time in enumerate(st.session_state['selected_times']):
|
228 |
-
start_time_obj = datetime.datetime.strptime(start_time, '%H:%M:%S')
|
229 |
-
end_time_obj = start_time_obj + datetime.timedelta(minutes=1)
|
230 |
-
|
231 |
-
# μμ μκ°κ³Ό λ μκ°μ HH:MM:SS νμμΌλ‘ λ³ν
|
232 |
-
start_time_str = start_time_obj.strftime('%H:%M:%S')
|
233 |
-
end_time_str = end_time_obj.strftime('%H:%M:%S')
|
234 |
-
|
235 |
-
# yt-dlp λ€μ΄λ‘λ λͺ
λ Ήμ΄ μ€ν
|
236 |
-
output_filename = f"clip_{idx + 1}.mp4"
|
237 |
-
ydl_opts = {
|
238 |
-
'outtmpl': os.path.join(os.path.expanduser("~/Downloads"), output_filename),
|
239 |
-
'download_sections': [f"*{start_time_str}-{end_time_str}"]
|
240 |
-
}
|
241 |
-
|
242 |
-
st.write(f"λ€μ΄λ‘λ μ€: {start_time_str} ~ {end_time_str} | νμΌλͺ
: {output_filename}")
|
243 |
-
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
244 |
-
ydl.download([vod_url]) # μλ URL μ¬μ©
|
245 |
|
246 |
# λ€μ΄λ‘λ λ²νΌ νμ
|
247 |
if st.button("μ νλ μκ°λμ μμ λ€μ΄λ‘λ"):
|
|
|
16 |
st.title("VOD μ±ν
ν¬λ‘€λ¬")
|
17 |
st.write("VOD URLμ μ
λ ₯νκ³ μ±ν
λ°μ΄ν°λ₯Ό ν¬λ‘€λ§ν©λλ€.")
|
18 |
|
19 |
+
# URL μ
λ ₯ λ°κΈ°
|
20 |
vod_url = st.text_input("VOD URL μ
λ ₯")
|
21 |
|
22 |
# μ νλ μκ°λλ₯Ό μ μ₯ν 곡κ°
|
|
|
25 |
|
26 |
# μ±ν
ν¬λ‘€λ§ ν¨μ
|
27 |
def crawl_chats(vod_url):
|
28 |
+
# URL μ€μ
|
29 |
url = vod_url + "/chats"
|
30 |
|
31 |
# μμ² ν€λ (νμμ μΏ ν€λ κΈ°ν ν€λ μ 보 μΆκ°)
|
|
|
47 |
chat_counts = defaultdict(int)
|
48 |
laugh_counts = defaultdict(int)
|
49 |
total_chats_collected = 0 # μ΄ μμ§λ μ±ν
κ°μ
|
50 |
+
start_time = time.time() # ν¬λ‘€λ§ μμ μκ°
|
51 |
|
52 |
# μ±ν
λ°μ΄ν°λ₯Ό μμ°¨μ μΌλ‘ μμ²νμ¬ κ°μ Έμ€κΈ°
|
53 |
status_text = st.empty() # μν λ©μμ§ μΆλ ₯μ©
|
|
|
|
|
54 |
while True:
|
55 |
# API μμ² λ³΄λ΄κΈ°
|
56 |
response = requests.get(url, params=params, headers=headers)
|
|
|
104 |
laugh_counts[minute_key] += 1
|
105 |
|
106 |
total_chats_collected += len(chats)
|
107 |
+
elapsed_time = time.time() - start_time # κ²½κ³Ό μκ° κ³μ°
|
|
|
|
|
108 |
status_text.text(f"νμ¬κΉμ§ μμ§λ μ±ν
λ©μμ§ κ°μ: {total_chats_collected} | κ²½κ³Ό μκ°: {int(elapsed_time // 60)}λΆ {int(elapsed_time % 60)}μ΄")
|
109 |
|
110 |
# λ€μ μμ²μ μν΄ playerMessageTime νλΌλ―Έν° μ
λ°μ΄νΈ
|
|
|
115 |
|
116 |
return "\n".join(chat_logs), chat_counts, laugh_counts
|
117 |
|
118 |
+
# μ νλ μκ°λλ₯Ό νμ λ° μμ κΈ°λ₯
|
119 |
+
def display_selected_times():
|
120 |
+
if st.session_state['selected_times']:
|
121 |
+
st.write("### μ νλ μκ°λ")
|
122 |
+
for time in st.session_state['selected_times']:
|
123 |
+
col1, col2 = st.columns([9, 1])
|
124 |
+
col1.write(f"{time}")
|
125 |
+
if col2.button("X", key=f"remove_{time}"):
|
126 |
+
st.session_state['selected_times'].remove(time)
|
127 |
+
|
128 |
+
# yt-dlpλ₯Ό μ¬μ©νμ¬ μ νλ μκ°λμ μμμ λ€μ΄λ‘λ
|
129 |
+
def download_clips():
|
130 |
+
if st.session_state['selected_times']:
|
131 |
+
st.write("### μμ λ€μ΄λ‘λ")
|
132 |
+
for idx, start_time in enumerate(st.session_state['selected_times']):
|
133 |
+
start_time_obj = datetime.datetime.strptime(start_time, '%H:%M:%S')
|
134 |
+
end_time_obj = start_time_obj + datetime.timedelta(minutes=1)
|
135 |
+
|
136 |
+
# μμ μκ°κ³Ό λ μκ°μ HH:MM:SS νμμΌλ‘ λ³ν
|
137 |
+
start_time_str = start_time_obj.strftime('%H:%M:%S')
|
138 |
+
end_time_str = end_time_obj.strftime('%H:%M:%S')
|
139 |
+
|
140 |
+
# yt-dlp λ€μ΄λ‘λ λͺ
λ Ήμ΄ μ€ν
|
141 |
+
output_filename = f"clip_{idx + 1}.mp4"
|
142 |
+
ydl_opts = {
|
143 |
+
'outtmpl': os.path.join(os.path.expanduser("~/Downloads"), output_filename), # Downloads ν΄λμ μ μ₯
|
144 |
+
'download_sections': [f"*{start_time_str}-{end_time_str}"]
|
145 |
+
}
|
146 |
+
|
147 |
+
st.write(f"λ€μ΄λ‘λ μ€: {start_time_str} ~ {end_time_str} | νμΌλͺ
: {output_filename}")
|
148 |
+
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
149 |
+
ydl.download([vod_url]) # μλ URL μ¬μ©
|
150 |
+
|
151 |
# λ²νΌμ λλ μ λ μ±ν
ν¬λ‘€λ§ μμ
|
152 |
if 'chat_logs' not in st.session_state:
|
153 |
st.session_state['chat_logs'] = None
|
|
|
216 |
title="λΆλΉ μ±ν
λ° γ
γ
γ
γ
μ±ν
κ°μ",
|
217 |
xaxis_title="μκ°",
|
218 |
yaxis_title="μ±ν
κ°μ",
|
219 |
+
height=600, # κ·Έλν λμ΄ μ€μ
|
220 |
xaxis=dict(showticklabels=False), # xμΆ μκ° λ μ΄λΈ μ¨κΉ
|
221 |
hovermode="x unified", # λ§μ°μ€λ₯Ό μ¬λ Έμ λ ν΄λΉ xμΆμμ ν΄ν νμ
|
222 |
showlegend=True,
|
|
|
244 |
minute = 0
|
245 |
|
246 |
# μ νλ μκ°λλ₯Ό νμ λ° μμ κΈ°λ₯
|
247 |
+
display_selected_times()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
248 |
|
249 |
# λ€μ΄λ‘λ λ²νΌ νμ
|
250 |
if st.button("μ νλ μκ°λμ μμ λ€μ΄λ‘λ"):
|