lisonallen commited on
Commit
0236769
·
1 Parent(s): a99823b

修复HuggingFace Space中自动生成问题:添加任务状态跟踪及确保不会并发运行

Browse files
Files changed (1) hide show
  1. app.py +175 -216
app.py CHANGED
@@ -854,165 +854,196 @@ def worker(input_image, prompt, n_prompt, seed, total_second_length, latent_wind
854
  return
855
 
856
 
857
- # 使用Hugging Face Spaces GPU装饰器处理进程函数
858
- if IN_HF_SPACE and 'spaces' in globals():
859
- @spaces.GPU
860
- def process_with_gpu(input_image, prompt, n_prompt, seed, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, use_teacache):
861
- global stream
862
- assert input_image is not None, 'No input image!'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
863
 
864
- # 初始化UI状态
865
- yield None, None, '', '', gr.update(interactive=False), gr.update(interactive=True)
 
 
866
 
 
 
867
  try:
868
- stream = AsyncStream()
 
 
 
 
 
 
 
 
869
 
870
- # 异步启动worker
871
- async_run(worker, input_image, prompt, n_prompt, seed, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, use_teacache)
872
 
873
- output_filename = None
874
- prev_output_filename = None
875
- error_message = None
876
 
877
- # 持续检查worker的输出
878
- while True:
879
- try:
880
- flag, data = stream.output_queue.next()
881
-
882
- if flag == 'file':
883
- output_filename = data
884
- prev_output_filename = output_filename
885
- # 清除错误显示,确保文件成功时不显示错误
886
- yield output_filename, gr.update(), gr.update(), '', gr.update(interactive=False), gr.update(interactive=True)
887
-
888
- if flag == 'progress':
889
- preview, desc, html = data
890
- # 更新进度时不改变错误信息
891
- yield gr.update(), gr.update(visible=True, value=preview), desc, html, gr.update(interactive=False), gr.update(interactive=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
892
 
893
- if flag == 'error':
894
- error_message = data
895
- print(f"收到错误消息: {error_message}")
896
- # 不立即显示,等待end信号
897
-
898
- if flag == 'end':
899
- # 如果有最后的视频文件,确保返回
900
- if output_filename is None and prev_output_filename is not None:
901
- output_filename = prev_output_filename
902
-
903
- # 如果有错误消息,创建友好的错误显示
904
- if error_message:
905
- error_html = create_error_html(error_message)
906
- yield output_filename, gr.update(visible=False), gr.update(), error_html, gr.update(interactive=True), gr.update(interactive=False)
907
- else:
908
- # 确保成功完成时不显示任何错误
909
- yield output_filename, gr.update(visible=False), gr.update(), '', gr.update(interactive=True), gr.update(interactive=False)
910
- break
911
- except Exception as e:
912
- print(f"处理输出时出错: {e}")
913
- # 检查是否长时间没有更新
914
- current_time = time.time()
915
- if current_time - last_update_time > 60: # 60秒没有更新,可能卡住了
916
- print(f"处理似乎卡住了,已经 {current_time - last_update_time:.1f} 秒没有更新")
917
-
918
- # 如果有部分生成的视频,返回
919
- if prev_output_filename:
920
- error_html = create_error_html("处理超时,但已生成部分视频", is_timeout=True)
921
- yield prev_output_filename, gr.update(visible=False), gr.update(), error_html, gr.update(interactive=True), gr.update(interactive=False)
922
- else:
923
- error_html = create_error_html(f"处理超时: {e}", is_timeout=True)
924
- yield None, gr.update(visible=False), gr.update(), error_html, gr.update(interactive=True), gr.update(interactive=False)
925
- break
926
 
927
- except Exception as e:
928
- print(f"启动处理时出错: {e}")
929
- traceback.print_exc()
930
- error_msg = str(e)
931
-
932
- error_html = create_error_html(error_msg)
933
- yield None, gr.update(visible=False), gr.update(), error_html, gr.update(interactive=True), gr.update(interactive=False)
934
-
935
- process = process_with_gpu
936
- else:
937
- def process(input_image, prompt, n_prompt, seed, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, use_teacache):
938
- global stream
939
- assert input_image is not None, 'No input image!'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
940
 
941
- # 初始化UI状态
942
- yield None, None, '', '', gr.update(interactive=False), gr.update(interactive=True)
 
 
 
943
 
944
- try:
945
- stream = AsyncStream()
946
 
947
- # 异步启动worker
948
- async_run(worker, input_image, prompt, n_prompt, seed, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, use_teacache)
 
 
 
 
949
 
950
- output_filename = None
951
- prev_output_filename = None
952
- error_message = None
953
 
954
- # 持续检查worker的输出
955
- while True:
956
- try:
957
- flag, data = stream.output_queue.next()
958
-
959
- if flag == 'file':
960
- output_filename = data
961
- prev_output_filename = output_filename
962
- # 清除错误显示,确保文件成功时不显示错误
963
- yield output_filename, gr.update(), gr.update(), '', gr.update(interactive=False), gr.update(interactive=True)
964
-
965
- if flag == 'progress':
966
- preview, desc, html = data
967
- # 更新进度时不改变错误信息
968
- yield gr.update(), gr.update(visible=True, value=preview), desc, html, gr.update(interactive=False), gr.update(interactive=True)
969
-
970
- if flag == 'error':
971
- error_message = data
972
- print(f"收到错误消息: {error_message}")
973
- # 不立即显示,等待end信号
974
-
975
- if flag == 'end':
976
- # 如果有最后的视频文件,确保返回
977
- if output_filename is None and prev_output_filename is not None:
978
- output_filename = prev_output_filename
979
-
980
- # 如果有错误消息,创建友好的错误显示
981
- if error_message:
982
- error_html = create_error_html(error_message)
983
- yield output_filename, gr.update(visible=False), gr.update(), error_html, gr.update(interactive=True), gr.update(interactive=False)
984
- else:
985
- # 确保成功完成时不显示任何错误
986
- yield output_filename, gr.update(visible=False), gr.update(), '', gr.update(interactive=True), gr.update(interactive=False)
987
- break
988
- except Exception as e:
989
- print(f"处理输出时出错: {e}")
990
- # 检查是否长时间没有更新
991
- current_time = time.time()
992
- if current_time - last_update_time > 60: # 60秒没有更新,可能卡住了
993
- print(f"处理似乎卡住了,已经 {current_time - last_update_time:.1f} 秒没有更新")
994
-
995
- # 如果有部分生成的视频,返回
996
- if prev_output_filename:
997
- error_html = create_error_html("处理超时,但已生成部分视频", is_timeout=True)
998
- yield prev_output_filename, gr.update(visible=False), gr.update(), error_html, gr.update(interactive=True), gr.update(interactive=False)
999
- else:
1000
- error_html = create_error_html(f"处理超时: {e}", is_timeout=True)
1001
- yield None, gr.update(visible=False), gr.update(), error_html, gr.update(interactive=True), gr.update(interactive=False)
1002
- break
1003
-
1004
- except Exception as e:
1005
- print(f"启动处理时出错: {e}")
1006
- traceback.print_exc()
1007
- error_msg = str(e)
1008
-
1009
- error_html = create_error_html(error_msg)
1010
- yield None, gr.update(visible=False), gr.update(), error_html, gr.update(interactive=True), gr.update(interactive=False)
1011
 
 
 
1012
 
1013
- def end_process():
1014
- stream.input_queue.push('end')
 
 
 
 
 
1015
 
 
1016
 
1017
  quick_prompts = [
1018
  'The girl dances gracefully, with clear movements, full of charm.',
@@ -1504,77 +1535,5 @@ with block:
1504
 
1505
  # 错误信息区域 - 确保使用HTML组件以支持我们的自定义错误消息格式
1506
  error_message = gr.HTML('', elem_id='error-message', visible=True)
1507
-
1508
- # 处理函数
1509
- ips = [input_image, prompt, n_prompt, seed, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, use_teacache]
1510
-
1511
- # 开始和结束按钮事件
1512
- start_button.click(fn=process, inputs=ips, outputs=[result_video, preview_image, progress_desc, progress_bar, start_button, end_button])
1513
- end_button.click(fn=end_process)
1514
-
1515
-
1516
- block.launch()
1517
 
1518
- # 创建友好的错误显示HTML
1519
- def create_error_html(error_msg, is_timeout=False):
1520
- """创建双语错误消息HTML"""
1521
- # 提供更友好的中英文双语错误信息
1522
- en_msg = ""
1523
- zh_msg = ""
1524
-
1525
- if is_timeout:
1526
- en_msg = "Processing timed out, but partial video may have been generated" if "部分视频" in error_msg else f"Processing timed out: {error_msg}"
1527
- zh_msg = "处理超时,但已生成部分视频" if "部分视频" in error_msg else f"处理超时: {error_msg}"
1528
- elif "模型加载失败" in error_msg:
1529
- en_msg = "Failed to load models. The Space may be experiencing high traffic or GPU issues."
1530
- zh_msg = "模型加载失败,可能是Space流量过高或GPU资源不足。"
1531
- elif "GPU" in error_msg or "CUDA" in error_msg or "内存" in error_msg or "memory" in error_msg:
1532
- en_msg = "GPU memory insufficient or GPU error. Try increasing GPU memory preservation value or reduce video length."
1533
- zh_msg = "GPU内存不足或GPU错误��请尝试增加GPU推理保留内存值或降低视频长度。"
1534
- elif "采样过程中出错" in error_msg:
1535
- if "部分" in error_msg:
1536
- en_msg = "Error during sampling process, but partial video has been generated."
1537
- zh_msg = "采样过程中出错,但已生成部分视频。"
1538
- else:
1539
- en_msg = "Error during sampling process. Unable to generate video."
1540
- zh_msg = "采样过程中出错,无法生成视频。"
1541
- elif "模型下载超时" in error_msg or "网络连接不稳定" in error_msg or "ReadTimeoutError" in error_msg or "ConnectionError" in error_msg:
1542
- en_msg = "Network connection is unstable, model download timed out. Please try again later."
1543
- zh_msg = "网络连接不稳定,模型下载超时。请稍后再试。"
1544
- elif "VAE" in error_msg or "解码" in error_msg or "decode" in error_msg:
1545
- en_msg = "Error during video decoding or saving process. Try again with a different seed."
1546
- zh_msg = "视频解码或保存过程中出错,请尝试使用不同的随机种子。"
1547
- else:
1548
- en_msg = f"Processing error: {error_msg}"
1549
- zh_msg = f"处理过程出错: {error_msg}"
1550
-
1551
- # 创建双语错误消息HTML - 添加有用的图标并确保CSS样式适用
1552
- return f"""
1553
- <div class="error-message" id="custom-error-container">
1554
- <div class="error-msg-en" data-lang="en">
1555
- <span class="error-icon">⚠️</span> {en_msg}
1556
- </div>
1557
- <div class="error-msg-zh" data-lang="zh">
1558
- <span class="error-icon">⚠️</span> {zh_msg}
1559
- </div>
1560
- </div>
1561
- <script>
1562
- // 根据当前语言显示相应的错误消息
1563
- (function() {{
1564
- const errorContainer = document.getElementById('custom-error-container');
1565
- if (errorContainer) {{
1566
- const currentLang = window.currentLang || 'en'; // 默认英语
1567
- const errMsgs = errorContainer.querySelectorAll('[data-lang]');
1568
- errMsgs.forEach(msg => {{
1569
- msg.style.display = msg.getAttribute('data-lang') === currentLang ? 'block' : 'none';
1570
- }});
1571
-
1572
- // 确保Gradio默认错误UI不显示
1573
- const defaultErrorElements = document.querySelectorAll('.error');
1574
- defaultErrorElements.forEach(el => {{
1575
- el.style.display = 'none';
1576
- }});
1577
- }}
1578
- }})();
1579
- </script>
1580
- """
 
854
  return
855
 
856
 
857
+ # 创建友好的错误显示HTML
858
+ def create_error_html(error_msg, is_timeout=False):
859
+ """创建双语错误消息HTML"""
860
+ # 提供更友好的中英文双语错误信息
861
+ en_msg = ""
862
+ zh_msg = ""
863
+
864
+ if is_timeout:
865
+ en_msg = "Processing timed out, but partial video may have been generated" if "部分视频" in error_msg else f"Processing timed out: {error_msg}"
866
+ zh_msg = "处理超时,但已生成部分视频" if "部分视频" in error_msg else f"处理超时: {error_msg}"
867
+ elif "模型加载失败" in error_msg:
868
+ en_msg = "Failed to load models. The Space may be experiencing high traffic or GPU issues."
869
+ zh_msg = "模型加载失败,可能是Space流量过高或GPU资源不足。"
870
+ elif "GPU" in error_msg or "CUDA" in error_msg or "内存" in error_msg or "memory" in error_msg:
871
+ en_msg = "GPU memory insufficient or GPU error. Try increasing GPU memory preservation value or reduce video length."
872
+ zh_msg = "GPU内存不足或GPU错误,请尝试增加GPU推理保留内存值或降低视频长度。"
873
+ elif "采样过程中出错" in error_msg:
874
+ if "部分" in error_msg:
875
+ en_msg = "Error during sampling process, but partial video has been generated."
876
+ zh_msg = "采样过程中出错,但已生成部分视频。"
877
+ else:
878
+ en_msg = "Error during sampling process. Unable to generate video."
879
+ zh_msg = "采样过程中出错,无法生成视频。"
880
+ elif "模型下载超时" in error_msg or "网络连接不稳定" in error_msg or "ReadTimeoutError" in error_msg or "ConnectionError" in error_msg:
881
+ en_msg = "Network connection is unstable, model download timed out. Please try again later."
882
+ zh_msg = "网络连接不稳定,模型下载超时。请稍后再试。"
883
+ elif "VAE" in error_msg or "解码" in error_msg or "decode" in error_msg:
884
+ en_msg = "Error during video decoding or saving process. Try again with a different seed."
885
+ zh_msg = "视频解码或保存过程中出错,请尝试使用不同的随机种子。"
886
+ else:
887
+ en_msg = f"Processing error: {error_msg}"
888
+ zh_msg = f"处理过程出错: {error_msg}"
889
+
890
+ # 创建双语错误消息HTML - 添加有用的图标并确保CSS样式适用
891
+ return f"""
892
+ <div class="error-message" id="custom-error-container">
893
+ <div class="error-msg-en" data-lang="en">
894
+ <span class="error-icon">⚠️</span> {en_msg}
895
+ </div>
896
+ <div class="error-msg-zh" data-lang="zh">
897
+ <span class="error-icon">⚠️</span> {zh_msg}
898
+ </div>
899
+ </div>
900
+ <script>
901
+ // 根据当前语言显示相应的错误消息
902
+ (function() {{
903
+ const errorContainer = document.getElementById('custom-error-container');
904
+ if (errorContainer) {{
905
+ const currentLang = window.currentLang || 'en'; // 默认英语
906
+ const errMsgs = errorContainer.querySelectorAll('[data-lang]');
907
+ errMsgs.forEach(msg => {{
908
+ msg.style.display = msg.getAttribute('data-lang') === currentLang ? 'block' : 'none';
909
+ }});
910
+
911
+ // 确保Gradio默认错误UI不显示
912
+ const defaultErrorElements = document.querySelectorAll('.error');
913
+ defaultErrorElements.forEach(el => {{
914
+ el.style.display = 'none';
915
+ }});
916
+ }}
917
+ }})();
918
+ </script>
919
+ """
920
 
921
+ # 修改process函数,添加任务状态检查
922
+ def process(input_image, prompt, n_prompt, seed, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, use_teacache):
923
+ global stream
924
+ assert input_image is not None, 'No input image!'
925
 
926
+ # 检查是否有正在运行的任务并清理
927
+ if hasattr(stream, 'is_running') and stream.is_running:
928
  try:
929
+ # 终止现有任务
930
+ stream.input_queue.push('end')
931
+ time.sleep(0.5) # 给一点时间让旧任务结束
932
+ except:
933
+ pass
934
+
935
+ # 创建新的流实例
936
+ stream = AsyncStream()
937
+ stream.is_running = True
938
 
939
+ # 初���化UI状态
940
+ yield None, None, '', '', gr.update(interactive=False), gr.update(interactive=True)
941
 
942
+ try:
943
+ # 异步启动worker
944
+ async_run(worker, input_image, prompt, n_prompt, seed, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, use_teacache)
945
 
946
+ output_filename = None
947
+ prev_output_filename = None
948
+ error_message = None
949
+
950
+ # 持续检查worker的输出
951
+ while True:
952
+ try:
953
+ flag, data = stream.output_queue.next()
954
+
955
+ if flag == 'file':
956
+ output_filename = data
957
+ prev_output_filename = output_filename
958
+ # 清除错误显示,确保文件成功时不显示错误
959
+ yield output_filename, gr.update(), gr.update(), '', gr.update(interactive=False), gr.update(interactive=True)
960
+
961
+ if flag == 'progress':
962
+ preview, desc, html = data
963
+ # 更新进度时不改变错误信息
964
+ yield gr.update(), gr.update(visible=True, value=preview), desc, html, gr.update(interactive=False), gr.update(interactive=True)
965
+
966
+ if flag == 'error':
967
+ error_message = data
968
+ print(f"收到错误消息: {error_message}")
969
+ # 不立即显示,等待end信号
970
+
971
+ if flag == 'end':
972
+ # 如果有最后的视频文件,确保返回
973
+ if output_filename is None and prev_output_filename is not None:
974
+ output_filename = prev_output_filename
975
 
976
+ # 如果有错误消息,创建友好的错误显示
977
+ if error_message:
978
+ error_html = create_error_html(error_message)
979
+ yield output_filename, gr.update(visible=False), gr.update(), error_html, gr.update(interactive=True), gr.update(interactive=False)
980
+ else:
981
+ # 确保成功完成时不显示任何错误
982
+ yield output_filename, gr.update(visible=False), gr.update(), '', gr.update(interactive=True), gr.update(interactive=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
983
 
984
+ # 标记任务已结束
985
+ stream.is_running = False
986
+ break
987
+ except Exception as e:
988
+ print(f"处理输出时出错: {e}")
989
+ # 检查是否长时间没有更新
990
+ current_time = time.time()
991
+ if current_time - last_update_time > 60: # 60秒没有更新,可能卡住了
992
+ print(f"处理似乎卡住了,已经 {current_time - last_update_time:.1f} 秒没有更新")
993
+
994
+ # 如果有部分生成的视频,返回
995
+ if prev_output_filename:
996
+ error_html = create_error_html("处理超时,但已生成部分视频", is_timeout=True)
997
+ yield prev_output_filename, gr.update(visible=False), gr.update(), error_html, gr.update(interactive=True), gr.update(interactive=False)
998
+ else:
999
+ error_html = create_error_html(f"处理超时: {e}", is_timeout=True)
1000
+ yield None, gr.update(visible=False), gr.update(), error_html, gr.update(interactive=True), gr.update(interactive=False)
1001
+
1002
+ # 标记任务已结束
1003
+ stream.is_running = False
1004
+ break
1005
+
1006
+ except Exception as e:
1007
+ print(f"启动处理时出错: {e}")
1008
+ traceback.print_exc()
1009
+ error_msg = str(e)
1010
+
1011
+ error_html = create_error_html(error_msg)
1012
+ yield None, gr.update(visible=False), gr.update(), error_html, gr.update(interactive=True), gr.update(interactive=False)
1013
+
1014
+ # 标记任务已结束
1015
+ stream.is_running = False
1016
 
1017
+ def end_process():
1018
+ if hasattr(stream, 'input_queue'):
1019
+ stream.input_queue.push('end')
1020
+ if hasattr(stream, 'is_running'):
1021
+ stream.is_running = False
1022
 
 
 
1023
 
1024
+ # 使用Hugging Face Spaces GPU装饰器处理进程函数
1025
+ if IN_HF_SPACE and 'spaces' in globals():
1026
+ @spaces.GPU
1027
+ def process_with_gpu(input_image, prompt, n_prompt, seed, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, use_teacache):
1028
+ # 调用普通的process函数实现,以避免重复代码
1029
+ return process(input_image, prompt, n_prompt, seed, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, use_teacache)
1030
 
1031
+ # 仅在环境中设置,不在这里覆盖process函数
1032
+ process_gpu = process_with_gpu
 
1033
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1034
 
1035
+ # 处理函数
1036
+ ips = [input_image, prompt, n_prompt, seed, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, use_teacache]
1037
 
1038
+ # 开始和结束按钮事件
1039
+ if IN_HF_SPACE and 'spaces' in globals() and GPU_AVAILABLE and not cpu_fallback_mode:
1040
+ # 使用带GPU装饰器的处理函数
1041
+ start_button.click(fn=process_gpu, inputs=ips, outputs=[result_video, preview_image, progress_desc, progress_bar, start_button, end_button])
1042
+ else:
1043
+ # 使用普通处理函数
1044
+ start_button.click(fn=process, inputs=ips, outputs=[result_video, preview_image, progress_desc, progress_bar, start_button, end_button])
1045
 
1046
+ end_button.click(fn=end_process)
1047
 
1048
  quick_prompts = [
1049
  'The girl dances gracefully, with clear movements, full of charm.',
 
1535
 
1536
  # 错误信息区域 - 确保使用HTML组件以支持我们的自定义错误消息格式
1537
  error_message = gr.HTML('', elem_id='error-message', visible=True)
 
 
 
 
 
 
 
 
 
 
1538
 
1539
+ block.launch()