@danhachuel/thunderbolt 0.4.87 → 0.4.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/main.py +71 -29
- package/hermes_ui/automation_worker.py +6 -4
- package/hermes_ui/pipeline_worker.py +6 -4
- package/package.json +1 -1
- package/sitecustomize.py +10 -1
package/app/main.py
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import sys
|
|
3
|
+
import io
|
|
3
4
|
|
|
4
5
|
os.environ["PYTHONIOENCODING"] = "utf-8"
|
|
5
6
|
os.environ["PYTHONUTF8"] = "1"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
|
|
8
|
+
def _force_utf8_stream(stream: object) -> object:
|
|
9
|
+
buffer = getattr(stream, "buffer", None)
|
|
10
|
+
encoding = str(getattr(stream, "encoding", "") or "").lower().replace("-", "_")
|
|
11
|
+
if buffer is not None and encoding != "utf_8":
|
|
12
|
+
return io.TextIOWrapper(buffer, encoding="utf-8", errors="replace", line_buffering=True)
|
|
13
|
+
return stream
|
|
14
|
+
|
|
15
|
+
_original_stdout, _original_stderr = sys.stdout, sys.stderr
|
|
16
|
+
sys.stdout = _force_utf8_stream(sys.stdout)
|
|
17
|
+
sys.stderr = _force_utf8_stream(sys.stderr)
|
|
10
18
|
|
|
11
19
|
import hashlib
|
|
12
20
|
import json
|
|
@@ -130,6 +138,16 @@ AI_STYLE_OPTIONS = [
|
|
|
130
138
|
]
|
|
131
139
|
|
|
132
140
|
WIDE_STYLE_OPTIONS = ["Pexels/Pixabay", "full_ia", "Apenas Música"]
|
|
141
|
+
CHANNEL_ASPECT_RATIO_OPTIONS = ["Landscape 16:9", "Portrait 9:16", "Square 1:1"]
|
|
142
|
+
CHANNEL_FORMAT_OPTIONS = ["wide", "Shorts", "Music"]
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def channel_video_source_value(value: Any) -> str:
|
|
146
|
+
return {"pexels": "Pexels/Pixabay", "full_ia": "full_ia", "music": "Apenas Música"}.get(str(value or "").strip(), str(value or "Pexels/Pixabay") if str(value or "").strip() in set(WIDE_STYLE_OPTIONS) else "Pexels/Pixabay")
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def channel_video_source_storage(value: str) -> str:
|
|
150
|
+
return {"Pexels/Pixabay": "pexels", "full_ia": "full_ia", "Apenas Música": "music"}.get(value, value)
|
|
133
151
|
MATERIAL_SOURCE_OPTIONS = ["Pexels", "Pixabay"]
|
|
134
152
|
|
|
135
153
|
VIDEO_LANGUAGE_OPTIONS = [
|
|
@@ -1289,10 +1307,11 @@ def render_channel_edit_form(channel: dict, youtube_account_ids: list[str], yout
|
|
|
1289
1307
|
edited_name = st.text_input("Nome do canal", value=str(channel.get("name") or ""))
|
|
1290
1308
|
edited_url = st.text_input("URL", value=str(channel.get("url") or ""))
|
|
1291
1309
|
edited_handle = st.text_input("Handle", value=str(channel.get("handle") or ""))
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1310
|
+
language_options = VIDEO_LANGUAGE_SELECTION_OPTIONS
|
|
1311
|
+
edited_language = st.selectbox("Idioma do roteiro", language_options, index=language_options.index(normalize_video_language(channel.get("language") or "pt")) if normalize_video_language(channel.get("language") or "pt") in language_options else 0, format_func=video_language_label)
|
|
1312
|
+
edited_style = st.selectbox("Fonte do vídeo", WIDE_STYLE_OPTIONS, index=WIDE_STYLE_OPTIONS.index(channel_video_source_value(channel.get("style_wide"))) if channel_video_source_value(channel.get("style_wide")) in WIDE_STYLE_OPTIONS else 0)
|
|
1313
|
+
edited_aspect = st.selectbox("Proporção do vídeo", CHANNEL_ASPECT_RATIO_OPTIONS, index=CHANNEL_ASPECT_RATIO_OPTIONS.index(str(channel.get("video_aspect_ratio") or "Landscape 16:9")) if str(channel.get("video_aspect_ratio") or "Landscape 16:9") in CHANNEL_ASPECT_RATIO_OPTIONS else 0)
|
|
1314
|
+
edited_format = st.selectbox("Formato", CHANNEL_FORMAT_OPTIONS, index=CHANNEL_FORMAT_OPTIONS.index(str(channel.get("format") or "wide")) if str(channel.get("format") or "wide") in CHANNEL_FORMAT_OPTIONS else 0)
|
|
1296
1315
|
edited_niche = st.text_input("Nicho", value=str(channel.get("niche") or channel_niche_label(channel) if channel_niche_label(channel) != "SEM NICHO CONFIGURADO" else "") )
|
|
1297
1316
|
with edit_cols[1]:
|
|
1298
1317
|
edited_blueprint = st.selectbox("Blueprint Padrão", blueprint_ids, index=blueprint_ids.index(current_blueprint) if current_blueprint in blueprint_ids else 0, format_func=lambda item: blueprint_labels.get(item, item or "Sem Blueprint padrão"))
|
|
@@ -1314,7 +1333,7 @@ def render_channel_edit_form(channel: dict, youtube_account_ids: list[str], yout
|
|
|
1314
1333
|
else:
|
|
1315
1334
|
update_channel(channel_id, {
|
|
1316
1335
|
"name": edited_name.strip(), "url": edited_url.strip(), "handle": edited_handle.strip(), "language": edited_language,
|
|
1317
|
-
"style_wide":
|
|
1336
|
+
"style_wide": channel_video_source_storage(edited_style), "video_aspect_ratio": edited_aspect, "format": edited_format,
|
|
1318
1337
|
"niche": edited_niche.strip(), "reference_channels": [item.strip() for item in re.split(r"[,|]", edited_niche) if item.strip()],
|
|
1319
1338
|
"default_blueprint_id": edited_blueprint.strip(), "blueprint_id": edited_blueprint.strip(),
|
|
1320
1339
|
"default_voice": edited_voice.strip(), "voice": edited_voice.strip(),
|
|
@@ -1982,7 +2001,10 @@ def render_tiktok_channels():
|
|
|
1982
2001
|
name = st.text_input("Nome canal", value=str(imported.get("name") or imported.get("username") or ""))
|
|
1983
2002
|
url = st.text_input("URL canal", value=str(imported.get("public_url") or imported.get("url") or ""))
|
|
1984
2003
|
handle = st.text_input("Handle canal", value=str(imported.get("handle") or ""))
|
|
1985
|
-
language = st.selectbox("Idioma",
|
|
2004
|
+
language = st.selectbox("Idioma do roteiro", VIDEO_LANGUAGE_SELECTION_OPTIONS, format_func=video_language_label, key="tiktok_import_language")
|
|
2005
|
+
source_value = st.selectbox("Fonte do vídeo", WIDE_STYLE_OPTIONS, key="tiktok_import_source")
|
|
2006
|
+
aspect_value = st.selectbox("Proporção do vídeo", CHANNEL_ASPECT_RATIO_OPTIONS, index=1, key="tiktok_import_aspect")
|
|
2007
|
+
format_value = st.selectbox("Formato", CHANNEL_FORMAT_OPTIONS, index=1, key="tiktok_import_format")
|
|
1986
2008
|
niche = st.text_input("Nicho", key="tiktok_import_niche")
|
|
1987
2009
|
prompt = st.selectbox("Prompt Master padrão", prompt_ids, format_func=lambda item: prompt_labels.get(item, item), key="tiktok_import_prompt")
|
|
1988
2010
|
voice = st.selectbox("Narrador/Voz Padrão", voice_options, format_func=lambda item: item or "Sem voz padrão", key="tiktok_import_voice")
|
|
@@ -1993,7 +2015,7 @@ def render_tiktok_channels():
|
|
|
1993
2015
|
if not valid_hhmm(automation_time):
|
|
1994
2016
|
st.error("O horário diário deve estar no formato HH:MM.")
|
|
1995
2017
|
st.stop()
|
|
1996
|
-
channel = create_channel(name.strip(), url.strip(), {"platform": "tiktok", "handle": handle.strip(), "language": language, "niche": niche.strip(), "description": description.strip(), "default_prompt_master": prompt, "prompt_master": prompt, "default_voice": voice, "voice": voice, "style_wide":
|
|
2018
|
+
channel = create_channel(name.strip(), url.strip(), {"platform": "tiktok", "handle": handle.strip(), "language": language, "niche": niche.strip(), "description": description.strip(), "default_prompt_master": prompt, "prompt_master": prompt, "default_voice": voice, "voice": voice, "style_wide": channel_video_source_storage(source_value), "video_aspect_ratio": aspect_value, "format": format_value, "automation_on": automation_on, "automation_time": automation_time.strip(), "metrics_source": "tiktok_public_page", "subscriber_count": imported.get("subscriber_count"), "video_count": imported.get("video_count")})
|
|
1997
2019
|
avatar_url = _tiktok_avatar_url(imported)
|
|
1998
2020
|
update_channel(channel["id"], {"platform": "tiktok", "default_prompt_master": prompt, "prompt_master": prompt, "avatar_url": avatar_url, "thumbnail_url": avatar_url})
|
|
1999
2021
|
st.session_state.pop("tiktok_channel_import", None)
|
|
@@ -2035,20 +2057,22 @@ def render_tiktok_channels():
|
|
|
2035
2057
|
if st.button("Apagar card", key=f"tiktok_import_card_delete_{channel_id}"):
|
|
2036
2058
|
st.session_state[f"tiktok_delete_{channel_id}"] = True
|
|
2037
2059
|
st.rerun()
|
|
2038
|
-
st.caption("Estilo wide: Portrait 9:16")
|
|
2039
|
-
st.caption(f"Automação: {'ligada' if automation_on else 'desligada'} · {automation_time}")
|
|
2040
2060
|
_, _, _, card_voice_options, card_current_voice = channel_default_options(channel)
|
|
2041
2061
|
selected_voice = st.selectbox("Narrador/Voz Padrão", card_voice_options, index=card_voice_options.index(card_current_voice) if card_current_voice in card_voice_options else 0, format_func=lambda item: item or "Sem voz padrão", key=f"tiktok_import_card_voice_{channel_id}")
|
|
2062
|
+
selected_source = st.selectbox("Fonte do vídeo", WIDE_STYLE_OPTIONS, index=WIDE_STYLE_OPTIONS.index(channel_video_source_value(channel.get("style_wide"))) if channel_video_source_value(channel.get("style_wide")) in WIDE_STYLE_OPTIONS else 0, key=f"tiktok_import_card_source_{channel_id}")
|
|
2063
|
+
selected_aspect = st.selectbox("Proporção do vídeo", CHANNEL_ASPECT_RATIO_OPTIONS, index=CHANNEL_ASPECT_RATIO_OPTIONS.index(str(channel.get("video_aspect_ratio") or "Portrait 9:16")) if str(channel.get("video_aspect_ratio") or "Portrait 9:16") in CHANNEL_ASPECT_RATIO_OPTIONS else 1, key=f"tiktok_import_card_aspect_{channel_id}")
|
|
2064
|
+
selected_format = st.selectbox("Formato", CHANNEL_FORMAT_OPTIONS, index=CHANNEL_FORMAT_OPTIONS.index(str(channel.get("format") or "Shorts")) if str(channel.get("format") or "Shorts") in CHANNEL_FORMAT_OPTIONS else 1, key=f"tiktok_import_card_format_{channel_id}")
|
|
2065
|
+
selected_language = st.selectbox("Idioma do roteiro", VIDEO_LANGUAGE_SELECTION_OPTIONS, index=VIDEO_LANGUAGE_SELECTION_OPTIONS.index(normalize_video_language(channel.get("language") or "pt")) if normalize_video_language(channel.get("language") or "pt") in VIDEO_LANGUAGE_SELECTION_OPTIONS else 0, format_func=video_language_label, key=f"tiktok_import_card_language_{channel_id}")
|
|
2042
2066
|
automation_on = st.toggle("Automação ON", value=bool(channel.get("automation_on", False)), key=f"tiktok_import_card_automation_{channel_id}")
|
|
2043
2067
|
automation_time = st.text_input("Horário diário (HH:MM)", value=str(channel.get("automation_time") or "00:00"), key=f"tiktok_import_card_time_{channel_id}")
|
|
2044
2068
|
if st.button("Guardar", key=f"tiktok_import_card_save_{channel_id}", use_container_width=True, type="primary"):
|
|
2045
2069
|
if not valid_hhmm(automation_time):
|
|
2046
2070
|
st.error("O horário diário deve estar no formato HH:MM.")
|
|
2047
2071
|
else:
|
|
2048
|
-
update_channel(channel_id, {"platform": "tiktok", "default_prompt_master": selected_prompt, "prompt_master": selected_prompt, "default_voice": selected_voice, "voice": selected_voice, "video_aspect_ratio": "
|
|
2072
|
+
update_channel(channel_id, {"platform": "tiktok", "default_prompt_master": selected_prompt, "prompt_master": selected_prompt, "default_voice": selected_voice, "voice": selected_voice, "language": selected_language, "video_aspect_ratio": selected_aspect, "format": selected_format, "style_wide": channel_video_source_storage(selected_source), "automation_on": automation_on, "automation_time": automation_time.strip()})
|
|
2049
2073
|
st.success("Dados do canal TikTok guardados.")
|
|
2050
2074
|
st.rerun()
|
|
2051
|
-
st.caption("
|
|
2075
|
+
st.caption(f"Fonte do vídeo: {channel_video_source_value(channel.get('style_wide'))}")
|
|
2052
2076
|
niche_action = st.columns([1.0, 4.0])
|
|
2053
2077
|
with niche_action[0]:
|
|
2054
2078
|
if st.button("Editar nicho", key=f"tiktok_import_card_niche_{channel_id}"):
|
|
@@ -2078,17 +2102,20 @@ def render_tiktok_channels():
|
|
|
2078
2102
|
edit_name = st.text_input("Nome do canal", value=str(channel.get("name") or ""))
|
|
2079
2103
|
edit_url = st.text_input("URL pública", value=str(channel.get("url") or ""))
|
|
2080
2104
|
edit_handle = st.text_input("Handle", value=str(channel.get("handle") or ""))
|
|
2081
|
-
edit_language = st.selectbox("Idioma do
|
|
2105
|
+
edit_language = st.selectbox("Idioma do roteiro", VIDEO_LANGUAGE_SELECTION_OPTIONS, index=VIDEO_LANGUAGE_SELECTION_OPTIONS.index(normalize_video_language(channel.get("language") or "pt")) if normalize_video_language(channel.get("language") or "pt") in VIDEO_LANGUAGE_SELECTION_OPTIONS else 0, format_func=video_language_label)
|
|
2106
|
+
edit_source = st.selectbox("Fonte do vídeo", WIDE_STYLE_OPTIONS, index=WIDE_STYLE_OPTIONS.index(channel_video_source_value(channel.get("style_wide"))) if channel_video_source_value(channel.get("style_wide")) in WIDE_STYLE_OPTIONS else 0)
|
|
2107
|
+
edit_aspect = st.selectbox("Proporção do vídeo", CHANNEL_ASPECT_RATIO_OPTIONS, index=CHANNEL_ASPECT_RATIO_OPTIONS.index(str(channel.get("video_aspect_ratio") or "Portrait 9:16")) if str(channel.get("video_aspect_ratio") or "Portrait 9:16") in CHANNEL_ASPECT_RATIO_OPTIONS else 1)
|
|
2108
|
+
edit_format = st.selectbox("Formato", CHANNEL_FORMAT_OPTIONS, index=CHANNEL_FORMAT_OPTIONS.index(str(channel.get("format") or "Shorts")) if str(channel.get("format") or "Shorts") in CHANNEL_FORMAT_OPTIONS else 1)
|
|
2082
2109
|
edit_voice = st.selectbox("Narrador/Voz Padrão", voice_options, index=voice_options.index(str(channel.get("default_voice") or channel.get("voice") or "")) if str(channel.get("default_voice") or channel.get("voice") or "") in voice_options else 0, format_func=lambda item: item or "Sem voz padrão")
|
|
2083
2110
|
edit_automation = st.toggle("Automação ON", value=bool(channel.get("automation_on", False)), key=f"tiktok_edit_automation_{channel_id}")
|
|
2084
2111
|
edit_time = st.text_input("Horário diário (HH:MM)", value=str(channel.get("automation_time") or "00:00"))
|
|
2085
|
-
st.caption("
|
|
2112
|
+
st.caption(f"Fonte do vídeo: {channel_video_source_value(channel.get('style_wide'))}")
|
|
2086
2113
|
edit_description = st.text_area("Descrição", value=str(channel.get("description") or ""))
|
|
2087
2114
|
if st.form_submit_button("Guardar edição", type="primary"):
|
|
2088
2115
|
if not valid_hhmm(edit_time):
|
|
2089
2116
|
st.error("O horário diário deve estar no formato HH:MM.")
|
|
2090
2117
|
else:
|
|
2091
|
-
update_channel(channel_id, {"name": edit_name.strip(), "url": edit_url.strip(), "handle": edit_handle.strip(), "language": edit_language, "default_voice": edit_voice, "voice": edit_voice, "style_wide":
|
|
2118
|
+
update_channel(channel_id, {"name": edit_name.strip(), "url": edit_url.strip(), "handle": edit_handle.strip(), "language": edit_language, "default_voice": edit_voice, "voice": edit_voice, "style_wide": channel_video_source_storage(edit_source), "video_aspect_ratio": edit_aspect, "format": edit_format, "automation_on": edit_automation, "automation_time": edit_time.strip(), "description": edit_description.strip(), "platform": "tiktok"})
|
|
2092
2119
|
st.session_state.pop(f"tiktok_edit_{channel_id}", None)
|
|
2093
2120
|
st.rerun()
|
|
2094
2121
|
with st.expander("Últimos 10 vídeos publicados", expanded=False):
|
|
@@ -2142,7 +2169,10 @@ def render_tiktok_channels():
|
|
|
2142
2169
|
url = st.text_input("URL canal", placeholder="https://www.tiktok.com/@conta", key="tiktok_manual_channel_url")
|
|
2143
2170
|
name = st.text_input("Nome canal", key="tiktok_manual_channel_name")
|
|
2144
2171
|
handle = st.text_input("Handle canal", key="tiktok_manual_channel_handle")
|
|
2145
|
-
language = st.selectbox("Idioma",
|
|
2172
|
+
language = st.selectbox("Idioma do roteiro", VIDEO_LANGUAGE_SELECTION_OPTIONS, format_func=video_language_label, key="tiktok_manual_channel_language")
|
|
2173
|
+
source_value = st.selectbox("Fonte do vídeo", WIDE_STYLE_OPTIONS, key="tiktok_manual_channel_source")
|
|
2174
|
+
aspect_value = st.selectbox("Proporção do vídeo", CHANNEL_ASPECT_RATIO_OPTIONS, index=1, key="tiktok_manual_channel_aspect")
|
|
2175
|
+
format_value = st.selectbox("Formato", CHANNEL_FORMAT_OPTIONS, index=1, key="tiktok_manual_channel_format")
|
|
2146
2176
|
niche = st.text_input("Nicho", key="tiktok_manual_channel_niche")
|
|
2147
2177
|
prompt = st.selectbox("Prompt Master padrão", prompt_ids, format_func=lambda item: prompt_labels.get(item, item), key="tiktok_manual_channel_prompt")
|
|
2148
2178
|
voice = st.selectbox("Narrador/Voz Padrão", voice_options, format_func=lambda item: item or "Sem voz padrão", key="tiktok_manual_channel_voice")
|
|
@@ -2155,7 +2185,7 @@ def render_tiktok_channels():
|
|
|
2155
2185
|
if not valid_hhmm(automation_time):
|
|
2156
2186
|
st.error("O horário diário deve estar no formato HH:MM.")
|
|
2157
2187
|
st.stop()
|
|
2158
|
-
channel = create_channel(name.strip() or reference["username"], reference["url"], {"platform": "tiktok", "handle": reference["handle"], "language": language, "niche": niche.strip(), "description": description.strip(), "default_prompt_master": prompt, "prompt_master": prompt, "default_voice": voice, "voice": voice, "style_wide":
|
|
2188
|
+
channel = create_channel(name.strip() or reference["username"], reference["url"], {"platform": "tiktok", "handle": reference["handle"], "language": language, "niche": niche.strip(), "description": description.strip(), "default_prompt_master": prompt, "prompt_master": prompt, "default_voice": voice, "voice": voice, "style_wide": channel_video_source_storage(source_value), "video_aspect_ratio": aspect_value, "format": format_value, "automation_on": automation_on, "automation_time": automation_time.strip()})
|
|
2159
2189
|
update_channel(channel["id"], {"platform": "tiktok"})
|
|
2160
2190
|
st.success("Canal TikTok cadastrado.")
|
|
2161
2191
|
st.rerun()
|
|
@@ -2231,8 +2261,10 @@ def render_channels():
|
|
|
2231
2261
|
name = st.text_input("Nome do canal", value=imported.get("name", ""), key="yt_import_name")
|
|
2232
2262
|
url = st.text_input("URL", value=imported.get("url", source if source.startswith("http") else ""), key="yt_import_url")
|
|
2233
2263
|
handle = st.text_input("Handle", value=imported.get("handle", ""), key="yt_import_handle")
|
|
2234
|
-
language = st.selectbox("Idioma",
|
|
2235
|
-
style = st.selectbox("
|
|
2264
|
+
language = st.selectbox("Idioma do roteiro", VIDEO_LANGUAGE_SELECTION_OPTIONS, index=VIDEO_LANGUAGE_SELECTION_OPTIONS.index(normalize_video_language(imported.get("language") or "pt")) if normalize_video_language(imported.get("language") or "pt") in VIDEO_LANGUAGE_SELECTION_OPTIONS else 0, format_func=video_language_label, key="yt_import_language")
|
|
2265
|
+
style = st.selectbox("Fonte do vídeo", WIDE_STYLE_OPTIONS, index=0, key="yt_import_style")
|
|
2266
|
+
video_aspect_ratio = st.selectbox("Proporção do vídeo", CHANNEL_ASPECT_RATIO_OPTIONS, key="yt_import_aspect_ratio")
|
|
2267
|
+
video_format = st.selectbox("Formato", CHANNEL_FORMAT_OPTIONS, key="yt_import_format")
|
|
2236
2268
|
blueprint = st.selectbox("Blueprint Padrão", blueprint_ids, index=blueprint_ids.index(imported_blueprint) if imported_blueprint in blueprint_ids else 0, format_func=lambda item: blueprint_labels.get(item, item or "Sem Blueprint padrão"), key="yt_import_blueprint")
|
|
2237
2269
|
voice_options = voice_catalog(imported.get("default_voice") or imported.get("voice", ""))
|
|
2238
2270
|
current_voice = imported.get("default_voice") or imported.get("voice", "")
|
|
@@ -2262,7 +2294,7 @@ def render_channels():
|
|
|
2262
2294
|
"niche": niche.strip(),
|
|
2263
2295
|
"reference_channels": [item.strip() for item in re.split(r"[,|]", niche) if item.strip()],
|
|
2264
2296
|
"language": language,
|
|
2265
|
-
"style_wide":
|
|
2297
|
+
"style_wide": channel_video_source_storage(style), "video_aspect_ratio": video_aspect_ratio, "format": video_format,
|
|
2266
2298
|
"blueprint_id": blueprint.strip(),
|
|
2267
2299
|
"default_blueprint_id": blueprint.strip(),
|
|
2268
2300
|
"default_voice": voice.strip(),
|
|
@@ -4968,14 +5000,18 @@ def render_tiktok_automation():
|
|
|
4968
5000
|
schedule_time = st.text_input("Horário (HH:MM)", value=channel.get("automation_time", "00:00"), key=f"tiktok_automation_time_{channel_id}")
|
|
4969
5001
|
default_cols = st.columns([1.0, 1.0, 1.35, 1.45, 1.55, 1.0], gap="small")
|
|
4970
5002
|
with default_cols[0]:
|
|
4971
|
-
st.markdown("**Idioma
|
|
4972
|
-
st.caption(
|
|
5003
|
+
st.markdown("**Idioma do roteiro**")
|
|
5004
|
+
st.caption(video_language_label(normalize_video_language(channel.get("language") or "pt")))
|
|
4973
5005
|
with default_cols[1]:
|
|
4974
5006
|
st.markdown("**Nicho Padrão**")
|
|
4975
5007
|
st.caption(channel_niche_label(channel))
|
|
4976
5008
|
with default_cols[2]:
|
|
4977
|
-
st.markdown("**
|
|
4978
|
-
st.caption("
|
|
5009
|
+
st.markdown("**Fonte do vídeo**")
|
|
5010
|
+
st.caption(channel_video_source_value(channel.get("style_wide")))
|
|
5011
|
+
st.markdown("**Proporção do vídeo**")
|
|
5012
|
+
st.caption(str(channel.get("video_aspect_ratio") or "Portrait 9:16"))
|
|
5013
|
+
st.markdown("**Formato**")
|
|
5014
|
+
st.caption(str(channel.get("format") or "Shorts"))
|
|
4979
5015
|
with default_cols[3]:
|
|
4980
5016
|
prompt = st.selectbox("Prompt Master Padrão", prompt_ids, index=prompt_ids.index(channel.get("default_prompt_master", "")) if channel.get("default_prompt_master", "") in prompt_ids else 0, format_func=lambda item: prompt_labels.get(item, item), key=f"tiktok_automation_prompt_{channel_id}")
|
|
4981
5017
|
with default_cols[4]:
|
|
@@ -5058,8 +5094,8 @@ def render_automation():
|
|
|
5058
5094
|
blueprint_ids, blueprint_labels, current_blueprint, voice_options, current_voice = channel_default_options(channel)
|
|
5059
5095
|
default_cols = st.columns([1.0, 1.0, 1.35, 1.45, 1.55, 1.0], gap="small")
|
|
5060
5096
|
with default_cols[0]:
|
|
5061
|
-
st.markdown("**Idioma
|
|
5062
|
-
st.caption(
|
|
5097
|
+
st.markdown("**Idioma do roteiro**")
|
|
5098
|
+
st.caption(video_language_label(normalize_video_language(channel.get("language") or "pt")))
|
|
5063
5099
|
with default_cols[1]:
|
|
5064
5100
|
st.markdown("**Nicho Padrão**")
|
|
5065
5101
|
st.caption(channel_niche_label(channel))
|
|
@@ -5073,6 +5109,12 @@ def render_automation():
|
|
|
5073
5109
|
)
|
|
5074
5110
|
with default_cols[2]:
|
|
5075
5111
|
paired_thumbnail = thumbnail_blueprint_for_blueprint(automation_blueprint)
|
|
5112
|
+
st.markdown("**Fonte do vídeo**")
|
|
5113
|
+
st.caption(channel_video_source_value(channel.get("style_wide")))
|
|
5114
|
+
st.markdown("**Proporção do vídeo**")
|
|
5115
|
+
st.caption(str(channel.get("video_aspect_ratio") or "Landscape 16:9"))
|
|
5116
|
+
st.markdown("**Formato**")
|
|
5117
|
+
st.caption(str(channel.get("format") or "wide"))
|
|
5076
5118
|
st.markdown("**Thumbnail Blueprint**")
|
|
5077
5119
|
st.caption(str(paired_thumbnail.get("name") or "Generic_Thumbnail_Blueprint"))
|
|
5078
5120
|
with default_cols[4]:
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import sys
|
|
3
|
+
import io
|
|
3
4
|
|
|
4
5
|
os.environ["PYTHONIOENCODING"] = "utf-8"
|
|
5
6
|
os.environ["PYTHONUTF8"] = "1"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
_original_stdout, _original_stderr = sys.stdout, sys.stderr
|
|
8
|
+
if getattr(sys.stdout, "buffer", None) is not None and str(getattr(sys.stdout, "encoding", "") or "").lower().replace("-", "_") != "utf_8":
|
|
9
|
+
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace", line_buffering=True)
|
|
10
|
+
if getattr(sys.stderr, "buffer", None) is not None and str(getattr(sys.stderr, "encoding", "") or "").lower().replace("-", "_") != "utf_8":
|
|
11
|
+
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8", errors="replace", line_buffering=True)
|
|
10
12
|
|
|
11
13
|
import argparse
|
|
12
14
|
import time
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import sys
|
|
3
|
+
import io
|
|
3
4
|
|
|
4
5
|
os.environ["PYTHONIOENCODING"] = "utf-8"
|
|
5
6
|
os.environ["PYTHONUTF8"] = "1"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
_original_stdout, _original_stderr = sys.stdout, sys.stderr
|
|
8
|
+
if getattr(sys.stdout, "buffer", None) is not None and str(getattr(sys.stdout, "encoding", "") or "").lower().replace("-", "_") != "utf_8":
|
|
9
|
+
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace", line_buffering=True)
|
|
10
|
+
if getattr(sys.stderr, "buffer", None) is not None and str(getattr(sys.stderr, "encoding", "") or "").lower().replace("-", "_") != "utf_8":
|
|
11
|
+
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8", errors="replace", line_buffering=True)
|
|
10
12
|
|
|
11
13
|
import json
|
|
12
14
|
import queue
|
package/package.json
CHANGED
package/sitecustomize.py
CHANGED
|
@@ -3,13 +3,22 @@ from __future__ import annotations
|
|
|
3
3
|
|
|
4
4
|
import os
|
|
5
5
|
import sys
|
|
6
|
+
import io
|
|
6
7
|
|
|
7
8
|
os.environ["PYTHONIOENCODING"] = "utf-8"
|
|
8
9
|
os.environ["PYTHONUTF8"] = "1"
|
|
9
10
|
|
|
10
11
|
for stream_name in ("stdin", "stdout", "stderr"):
|
|
11
12
|
stream = getattr(sys, stream_name, None)
|
|
12
|
-
if stream is not None
|
|
13
|
+
buffer = getattr(stream, "buffer", None) if stream is not None else None
|
|
14
|
+
encoding = str(getattr(stream, "encoding", "") or "").lower().replace("-", "_") if stream is not None else ""
|
|
15
|
+
if buffer is not None and encoding != "utf_8":
|
|
16
|
+
try:
|
|
17
|
+
replacement = io.TextIOWrapper(buffer, encoding="utf-8", errors="replace", line_buffering=True)
|
|
18
|
+
setattr(sys, stream_name, replacement)
|
|
19
|
+
except (OSError, ValueError):
|
|
20
|
+
pass
|
|
21
|
+
elif stream is not None and hasattr(stream, "reconfigure"):
|
|
13
22
|
try:
|
|
14
23
|
stream.reconfigure(encoding="utf-8", errors="replace")
|
|
15
24
|
except (OSError, ValueError):
|