Spaces:
Running
Running
| import streamlit as st | |
| import asyncio | |
| import httpx | |
| from pathlib import Path | |
| import os | |
| import base64 | |
| # Inicjalizacja katalogu wyj艣ciowego | |
| OUTPUT_DIR = "generated_videos" | |
| Path(OUTPUT_DIR).mkdir(parents=True, exist_ok=True) | |
| # Aktualne URL dla API Hailuo | |
| CREATE_URL = "https://api.minimaxi.chat/v1/video_generation" | |
| STATUS_URL = "https://api.minimaxi.chat/v1/query/video_generation" | |
| RETRIEVE_URL = "https://api.minimaxi.chat/v1/files/retrieve" | |
| def encode_image(image_path): | |
| """Konwertuje obraz na base64.""" | |
| with open(image_path, "rb") as image_file: | |
| encoded = base64.b64encode(image_file.read()).decode('utf-8') | |
| st.write(f"D艂ugo艣膰 base64 obrazu: {len(encoded)} znak贸w") # Debugowanie | |
| return encoded | |
| async def generate_video(api_key: str, prompt: str, optimize_prompt: bool = True, image: str = None) -> str: | |
| """Funkcja generuje film na podstawie promptu i opcjonalnego obrazu.""" | |
| headers = { | |
| "Content-Type": "application/json", | |
| "Authorization": f"Bearer {api_key}" | |
| } | |
| data = { | |
| "model": "video-01", | |
| "prompt": prompt, | |
| "prompt_optimizer": optimize_prompt # Dodana kontrola optymalizacji promptu | |
| } | |
| if image: | |
| if os.path.exists(image): # Je艣li to plik, przekonwertuj na base64 | |
| image = encode_image(image) | |
| data["first_frame_image"] = f"data:image/png;base64,{image}" # Poprawione przekazywanie base64 | |
| async with httpx.AsyncClient() as client: | |
| try: | |
| response = await client.post(CREATE_URL, headers=headers, json=data, timeout=60.0) | |
| response.raise_for_status() | |
| response_data = response.json() | |
| st.write("**Pe艂na odpowied藕 API:**") | |
| st.json(response_data) # Wy艣wietlanie pe艂nej odpowiedzi API | |
| task_id = response_data.get('task_id') | |
| if not task_id: | |
| st.error("Brak task_id w odpowiedzi API") | |
| return None | |
| max_retries = 60 # maksymalnie 10 minut przy 10s odst臋pie | |
| retry_count = 0 | |
| while retry_count < max_retries: | |
| status_response = await client.get(f"{STATUS_URL}?task_id={task_id}", headers=headers) | |
| status_response.raise_for_status() | |
| status_data = status_response.json() | |
| status = status_data.get('status') | |
| if status == "Success": | |
| file_id = status_data.get('file_id') | |
| if not file_id: | |
| st.error("Brak file_id w odpowiedzi API") | |
| return None | |
| retrieve_response = await client.get(f"{RETRIEVE_URL}?file_id={file_id}", headers=headers) | |
| retrieve_response.raise_for_status() | |
| retrieve_data = retrieve_response.json() | |
| download_url = retrieve_data.get('file', {}).get('download_url') | |
| if not download_url: | |
| st.error("Nie mo偶na pobra膰 URL dla pliku") | |
| return None | |
| file_response = await client.get(download_url) | |
| file_response.raise_for_status() | |
| output_path = os.path.join(OUTPUT_DIR, "generated_video.mp4") | |
| with open(output_path, 'wb') as f: | |
| f.write(file_response.content) | |
| return output_path | |
| elif status == "Fail": | |
| st.error(f"Generowanie filmu nie powiod艂o si臋: {status_data.get('status_msg')}") | |
| return None | |
| await asyncio.sleep(10) | |
| retry_count += 1 | |
| st.error("Przekroczono limit czasu podczas generowania filmu") | |
| return None | |
| except httpx.HTTPStatusError as http_err: | |
| st.error(f"HTTP error: {http_err.response.status_code} - {http_err.response.text}") | |
| return None | |
| except httpx.RequestError as req_err: | |
| st.error(f"Request error: {req_err}") | |
| return None | |
| except Exception as e: | |
| st.error(f"Wyst膮pi艂 b艂膮d: {e}") | |
| return None | |
| def main(): | |
| """Interfejs u偶ytkownika aplikacji.""" | |
| st.title("Generator Filmik贸w Hailuo") | |
| st.write("Wprowad藕 sw贸j klucz API, opis filmu i opcjonalnie obraz jako pierwsz膮 klatk臋.") | |
| api_key = st.text_input("Wprowad藕 sw贸j klucz API", type="password") | |
| prompt = st.text_area("Wprowad藕 opis filmu", "prompt") | |
| # Dodana kontrola optymalizacji promptu | |
| optimize_prompt = st.checkbox("Optymalizuj prompt", value=True, | |
| help="Gdy w艂膮czone, model automatycznie optymalizuje prompt dla lepszych rezultat贸w") | |
| image_option = st.radio("Wybierz spos贸b dodawania obrazu", ("Brak obrazu", "Wklej adres URL obrazu", "Prze艣lij obraz")) | |
| image = None | |
| if image_option == "Wklej adres URL obrazu": | |
| image = st.text_input("Wprowad藕 adres URL obrazu") | |
| elif image_option == "Prze艣lij obraz": | |
| uploaded_file = st.file_uploader("Prze艣lij obraz", type=["jpg", "jpeg", "png"]) | |
| if uploaded_file is not None: | |
| image_path = os.path.join(OUTPUT_DIR, uploaded_file.name) | |
| with open(image_path, "wb") as f: | |
| f.write(uploaded_file.getbuffer()) | |
| image = image_path | |
| if st.button("Generuj Film"): | |
| if not api_key: | |
| st.error("Prosz臋 wprowad藕 sw贸j klucz API.") | |
| return | |
| if not prompt: | |
| st.error("Prosz臋 wprowad藕 opis filmu.") | |
| return | |
| st.info("Rozpocz臋to generowanie filmu...") | |
| output_path = asyncio.run(generate_video(api_key, prompt, optimize_prompt, image)) | |
| if output_path: | |
| st.success("Film zosta艂 wygenerowany!") | |
| st.video(output_path) | |
| else: | |
| st.error("Wyst膮pi艂 b艂膮d podczas generowania filmu.") | |
| if __name__ == "__main__": | |
| main() |