maryna7679 commited on
Commit
897cf53
·
1 Parent(s): 21cce09
Files changed (1) hide show
  1. app.py +56 -69
app.py CHANGED
@@ -27,10 +27,10 @@ def on_row_select(df, evt: gr.SelectData):
27
  return (
28
  gr.update(visible=True), # editing_panel
29
  gr.update(value=float(row['Start'])), # start_time
30
- gr.update(value=str(row['Text'])), # text_input
31
- gr.update(value=float(row['End'])), # end_time
32
- gr.update(value=row_idx), # selected_row_idx
33
- gr.update(value="Update Entry") # save_entry_button
34
  )
35
  return gr.update(visible=False), "", "", "", -1, "Save Entry"
36
 
@@ -38,12 +38,12 @@ def on_row_select(df, evt: gr.SelectData):
38
  def show_add_entry_form():
39
  """Show editing panel for adding new entry"""
40
  return (
41
- gr.update(visible=True), # editing_panel
42
- gr.update(value=0.0), # start_time
43
- gr.update(value=""), # text_input
44
- gr.update(value=0.0), # end_time
45
- gr.update(value=-1), # selected_row_idx (-1 means new entry)
46
- gr.update(value="Add Entry") # save_entry_button
47
  )
48
 
49
 
@@ -54,15 +54,15 @@ def save_entry(df, start_time, text, end_time, selected_row_idx, video_id):
54
  try:
55
  start_time = float(start_time)
56
  end_time = float(end_time)
57
-
58
  if start_time >= end_time:
59
  return df, gr.update(visible=True), gr.Warning("Start time must be less than end time")
60
-
61
  if not text.strip():
62
  return df, gr.update(visible=True), gr.Warning("Text cannot be empty")
63
-
64
  df_copy = df.copy()
65
-
66
  if selected_row_idx == -1: # Adding new entry
67
  new_row = pd.DataFrame({
68
  'Start': [start_time],
@@ -77,7 +77,7 @@ def save_entry(df, start_time, text, end_time, selected_row_idx, video_id):
77
  df_copy.iloc[selected_row_idx] = [start_time, text.strip(), end_time]
78
  # Sort by start time
79
  df_copy = df_copy.sort_values('Start').reset_index(drop=True)
80
-
81
  # Update in database
82
  save_result = save_captions_to_db(df_copy, video_id, user)
83
 
@@ -86,7 +86,7 @@ def save_entry(df, start_time, text, end_time, selected_row_idx, video_id):
86
  gr.update(visible=False), # Hide panel on success
87
  gr.Info(f"{save_result}")
88
  )
89
-
90
  except ValueError as e:
91
  return df, gr.update(visible=True), gr.Warning(f"Invalid time format: {str(e)}")
92
  except Exception as e:
@@ -113,50 +113,49 @@ def get_next_components():
113
  except (ValueError, Exception) as e:
114
  empty_captions = pd.DataFrame(columns=["Start", "Text", "End"])
115
  return empty_captions, "error"
116
-
117
 
118
  (start_captions, start_video_id) = get_next_components()
119
 
120
  with gr.Blocks(css=css, head=yt_init_js, fill_width=True) as main_page:
 
 
121
 
122
- current_user = gr.Textbox(visible=False, interactive=False)
123
- current_video_id = gr.Textbox(value=start_video_id, visible=False, interactive=False)
124
  selected_row_idx = gr.Number(value=-1, visible=False)
125
 
126
- main_page.load(get_username, outputs=current_user) # Disabled when auth is disabled
127
 
128
  with gr.Row(variant="panel"):
129
  with gr.Column(scale=4):
130
  gr.Markdown("## Caption Editor")
131
  with gr.Column(scale=4):
132
- @gr.render(inputs=current_user)
133
  def check_login(logged_in_user):
134
- if logged_in_user is None:
135
  gr.Markdown("Please log in via Hugging Face", rtl=True)
136
  else:
137
- gr.Markdown(f"Logged in as {user}", rtl=True)
138
  with gr.Column(scale=1, min_width=50):
139
  gr.LoginButton(value="Log in", logout_value="Log in")
140
 
141
  with gr.Row():
142
  with gr.Column(scale=2, min_width=600):
143
- # Video player and "next video button
144
  video_embed = gr.HTML(value=get_youtube_player_html())
145
  next_video_button = gr.Button("Next", key="next_video")
146
  with gr.Column(scale=1, min_width=200):
147
- # Read-only DataFrame with add button
148
- caption_editor = gr.DataFrame(interactive=False,
149
- elem_id="tbl",
150
- value=start_captions,
151
- datatype=["number", "str", "number"],
152
- col_count=(3, "fixed"),
153
- column_widths=["20%", "60%", "20%"],
154
- headers=["Start", "Text", "End"],
155
- wrap=True)
156
  add_entry_button = gr.Button("Add Entry", variant="secondary")
157
 
158
  with gr.Row():
159
- # Editing panel (initially hidden) - spans full width
160
  with gr.Group(visible=False) as editing_panel:
161
  gr.Markdown("### Edit Caption Entry")
162
  with gr.Row(equal_height=False):
@@ -165,7 +164,6 @@ with gr.Blocks(css=css, head=yt_init_js, fill_width=True) as main_page:
165
  insert_start_time_button = gr.Button("Insert Current Time")
166
  with gr.Column():
167
  text_input = gr.Textbox(label="Caption Text", placeholder="Enter caption text...")
168
-
169
  with gr.Column():
170
  end_time_input = gr.Textbox(label="End Time (seconds)", value="0.000", interactive=False)
171
  insert_end_time_button = gr.Button("Insert Current Time")
@@ -176,41 +174,47 @@ with gr.Blocks(css=css, head=yt_init_js, fill_width=True) as main_page:
176
 
177
  save_result = gr.Markdown()
178
 
179
- # Event handlers
 
 
 
 
 
 
 
 
 
 
 
 
180
  next_video_button.click(
181
  fn=get_next_components,
182
  outputs=[caption_editor, current_video_id]
183
  )
184
 
185
- # Load video when current_video_id changes
186
  current_video_id.change(
187
  fn=None,
188
  inputs=current_video_id,
189
  outputs=None,
190
  js="""(videoId) => {
191
  if (window.ytPlayer && window.ytPlayer.cueVideoById) {
192
- console.log('[Video Load] Calling cueVideoById with:', videoId);
193
  window.ytPlayer.cueVideoById(videoId);
194
- } else {
195
- console.error('[Video Load] Player not ready yet');
196
  }
197
  }"""
198
  )
199
 
200
- # Handle row selection in DataFrame
201
  caption_editor.select(
202
  fn=on_row_select,
203
  inputs=[caption_editor],
204
  outputs=[editing_panel, start_time_input, text_input, end_time_input, selected_row_idx, save_entry_button]
205
  )
206
 
207
- # Handle add entry button
208
  add_entry_button.click(
209
  fn=show_add_entry_form,
210
  outputs=[editing_panel, start_time_input, text_input, end_time_input, selected_row_idx, save_entry_button]
211
  )
212
 
213
- # Handle save entry
214
  save_entry_button.click(
215
  fn=save_entry,
216
  inputs=[caption_editor, start_time_input, text_input, end_time_input,
@@ -218,32 +222,15 @@ with gr.Blocks(css=css, head=yt_init_js, fill_width=True) as main_page:
218
  outputs=[caption_editor, editing_panel, save_result]
219
  )
220
 
221
- insert_start_time_button.click(fn=None, inputs=None, outputs=start_time_input,
222
- js="() => window.ytPlayer ? +window.ytPlayer.getCurrentTime().toFixed(3) : 0")
223
-
224
- insert_end_time_button.click(fn=None, inputs=None, outputs=end_time_input,
225
- js="() => window.ytPlayer ? +window.ytPlayer.getCurrentTime().toFixed(3) : 0")
226
-
227
-
228
- # Handle cancel
229
- cancel_button.click(
230
- fn=cancel_edit,
231
- outputs=[editing_panel]
232
  )
233
-
234
- # Load initial video on page load
235
- main_page.load(
236
- fn=None,
237
- inputs=current_video_id,
238
- outputs=None,
239
- js="""(videoId) => {
240
- const checkPlayer = setInterval(() => {
241
- if (window.ytPlayer && window.ytPlayer.cueVideoById) {
242
- clearInterval(checkPlayer);
243
- window.ytPlayer.cueVideoById(videoId);
244
- }
245
- }, 100);
246
- }"""
247
  )
248
 
249
- main_page.launch(share=True)
 
 
 
27
  return (
28
  gr.update(visible=True), # editing_panel
29
  gr.update(value=float(row['Start'])), # start_time
30
+ gr.update(value=str(row['Text'])), # text_input
31
+ gr.update(value=float(row['End'])), # end_time
32
+ gr.update(value=row_idx), # selected_row_idx
33
+ gr.update(value="Update Entry") # save_entry_button
34
  )
35
  return gr.update(visible=False), "", "", "", -1, "Save Entry"
36
 
 
38
  def show_add_entry_form():
39
  """Show editing panel for adding new entry"""
40
  return (
41
+ gr.update(visible=True), # editing_panel
42
+ gr.update(value=0.0), # start_time
43
+ gr.update(value=""), # text_input
44
+ gr.update(value=0.0), # end_time
45
+ gr.update(value=-1), # selected_row_idx (-1 means new entry)
46
+ gr.update(value="Add Entry") # save_entry_button
47
  )
48
 
49
 
 
54
  try:
55
  start_time = float(start_time)
56
  end_time = float(end_time)
57
+
58
  if start_time >= end_time:
59
  return df, gr.update(visible=True), gr.Warning("Start time must be less than end time")
60
+
61
  if not text.strip():
62
  return df, gr.update(visible=True), gr.Warning("Text cannot be empty")
63
+
64
  df_copy = df.copy()
65
+
66
  if selected_row_idx == -1: # Adding new entry
67
  new_row = pd.DataFrame({
68
  'Start': [start_time],
 
77
  df_copy.iloc[selected_row_idx] = [start_time, text.strip(), end_time]
78
  # Sort by start time
79
  df_copy = df_copy.sort_values('Start').reset_index(drop=True)
80
+
81
  # Update in database
82
  save_result = save_captions_to_db(df_copy, video_id, user)
83
 
 
86
  gr.update(visible=False), # Hide panel on success
87
  gr.Info(f"{save_result}")
88
  )
89
+
90
  except ValueError as e:
91
  return df, gr.update(visible=True), gr.Warning(f"Invalid time format: {str(e)}")
92
  except Exception as e:
 
113
  except (ValueError, Exception) as e:
114
  empty_captions = pd.DataFrame(columns=["Start", "Text", "End"])
115
  return empty_captions, "error"
116
+
117
 
118
  (start_captions, start_video_id) = get_next_components()
119
 
120
  with gr.Blocks(css=css, head=yt_init_js, fill_width=True) as main_page:
121
+ user_state = gr.State("anonymous_user")
122
+ pointer_state = gr.State(0)
123
 
124
+ current_video_id = gr.Textbox(value="", visible=False, interactive=False)
 
125
  selected_row_idx = gr.Number(value=-1, visible=False)
126
 
127
+ main_page.load(get_username, outputs=user_state)
128
 
129
  with gr.Row(variant="panel"):
130
  with gr.Column(scale=4):
131
  gr.Markdown("## Caption Editor")
132
  with gr.Column(scale=4):
133
+ @gr.render(inputs=user_state)
134
  def check_login(logged_in_user):
135
+ if logged_in_user == "anonymous_user":
136
  gr.Markdown("Please log in via Hugging Face", rtl=True)
137
  else:
138
+ gr.Markdown(f"Logged in as {logged_in_user}", rtl=True)
139
  with gr.Column(scale=1, min_width=50):
140
  gr.LoginButton(value="Log in", logout_value="Log in")
141
 
142
  with gr.Row():
143
  with gr.Column(scale=2, min_width=600):
 
144
  video_embed = gr.HTML(value=get_youtube_player_html())
145
  next_video_button = gr.Button("Next", key="next_video")
146
  with gr.Column(scale=1, min_width=200):
147
+ caption_editor = gr.DataFrame(
148
+ interactive=False,
149
+ elem_id="tbl",
150
+ datatype=["number", "str", "number"],
151
+ col_count=(3, "fixed"),
152
+ column_widths=["20%", "60%", "20%"],
153
+ headers=["Start", "Text", "End"],
154
+ wrap=True
155
+ )
156
  add_entry_button = gr.Button("Add Entry", variant="secondary")
157
 
158
  with gr.Row():
 
159
  with gr.Group(visible=False) as editing_panel:
160
  gr.Markdown("### Edit Caption Entry")
161
  with gr.Row(equal_height=False):
 
164
  insert_start_time_button = gr.Button("Insert Current Time")
165
  with gr.Column():
166
  text_input = gr.Textbox(label="Caption Text", placeholder="Enter caption text...")
 
167
  with gr.Column():
168
  end_time_input = gr.Textbox(label="End Time (seconds)", value="0.000", interactive=False)
169
  insert_end_time_button = gr.Button("Insert Current Time")
 
174
 
175
  save_result = gr.Markdown()
176
 
177
+ main_page.load(
178
+ fn=get_next_components,
179
+ outputs=[caption_editor, current_video_id],
180
+ js="""() => {
181
+ const checkPlayer = setInterval(() => {
182
+ if (window.ytPlayer && window.ytPlayer.cueVideoById) {
183
+ clearInterval(checkPlayer);
184
+ // cue video dynamically once captions arrive
185
+ }
186
+ }, 100);
187
+ }"""
188
+ )
189
+
190
  next_video_button.click(
191
  fn=get_next_components,
192
  outputs=[caption_editor, current_video_id]
193
  )
194
 
 
195
  current_video_id.change(
196
  fn=None,
197
  inputs=current_video_id,
198
  outputs=None,
199
  js="""(videoId) => {
200
  if (window.ytPlayer && window.ytPlayer.cueVideoById) {
201
+ console.log('[Video Load] cueVideoById', videoId);
202
  window.ytPlayer.cueVideoById(videoId);
 
 
203
  }
204
  }"""
205
  )
206
 
 
207
  caption_editor.select(
208
  fn=on_row_select,
209
  inputs=[caption_editor],
210
  outputs=[editing_panel, start_time_input, text_input, end_time_input, selected_row_idx, save_entry_button]
211
  )
212
 
 
213
  add_entry_button.click(
214
  fn=show_add_entry_form,
215
  outputs=[editing_panel, start_time_input, text_input, end_time_input, selected_row_idx, save_entry_button]
216
  )
217
 
 
218
  save_entry_button.click(
219
  fn=save_entry,
220
  inputs=[caption_editor, start_time_input, text_input, end_time_input,
 
222
  outputs=[caption_editor, editing_panel, save_result]
223
  )
224
 
225
+ insert_start_time_button.click(
226
+ fn=None, inputs=None, outputs=start_time_input,
227
+ js="() => window.ytPlayer ? +window.ytPlayer.getCurrentTime().toFixed(3) : 0"
 
 
 
 
 
 
 
 
228
  )
229
+ insert_end_time_button.click(
230
+ fn=None, inputs=None, outputs=end_time_input,
231
+ js="() => window.ytPlayer ? +window.ytPlayer.getCurrentTime().toFixed(3) : 0"
 
 
 
 
 
 
 
 
 
 
 
232
  )
233
 
234
+ cancel_button.click(fn=cancel_edit, outputs=[editing_panel])
235
+
236
+ main_page.launch(share=True)