renderfy commited on
Commit
92e287d
·
verified ·
1 Parent(s): 9b31739

Upload 2 files

Browse files
Files changed (3) hide show
  1. .gitattributes +1 -0
  2. fitstudio_video.mp4 +3 -0
  3. streamlit_app.py +59 -47
.gitattributes CHANGED
@@ -34,3 +34,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  tryon.jpg filter=lfs diff=lfs merge=lfs -text
 
 
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  tryon.jpg filter=lfs diff=lfs merge=lfs -text
37
+ fitstudio_video.mp4 filter=lfs diff=lfs merge=lfs -text
fitstudio_video.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:679f85d356cdf3110c11ddfbc7a5537c5c6e0dbcadc5baca597312867cbdf63b
3
+ size 1919994
streamlit_app.py CHANGED
@@ -1,6 +1,6 @@
1
  # streamlit_app.py — Fit Studio AI (Fashion & Apparel) v0.4 UI
2
  # Still Image (VTO) → (optional) Runway Video
3
- # Demo preview: same folder "input.jpg" (girdi) ve "tryon.jpg" (örnek çıktı)
4
 
5
  import os, io, zipfile, requests, streamlit as st
6
  from pathlib import Path
@@ -41,9 +41,9 @@ PREVIEW_SIZE = int(os.getenv("PREVIEW_SIZE", "512"))
41
 
42
  # ================= Session State (ilk yük) =================
43
  defaults = {
44
- "results": None, # son çalıştırmanın sonuçları
45
- "job_counter": 0, # indirme butonları için unique key
46
- "duration": "6", # video süresi varsayılan
47
  }
48
  for k, v in defaults.items():
49
  if k not in st.session_state:
@@ -137,6 +137,27 @@ def show_tile(col, title, url: str | None, bg_rgb=(255,255,255), filename_stub="
137
  )
138
  return url, b
139
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  def make_zip(named_bytes: list[tuple[str, bytes]]) -> bytes:
141
  buf = io.BytesIO()
142
  with zipfile.ZipFile(buf, "w", compression=zipfile.ZIP_DEFLATED) as z:
@@ -186,16 +207,12 @@ c0, c1, c2, c3, c4 = st.columns([1.0, 1.8, 1.8, 1.4, 1.6])
186
 
187
  with c0:
188
  category = st.selectbox("Kategori", ["general","underwear"], index=0, key="category")
189
-
190
  with c1:
191
  file_list = st.file_uploader("Garment image (upload)", type=["jpg","jpeg","png","webp"], accept_multiple_files=True, key="file_upl")
192
-
193
  with c2:
194
  image_url = st.text_input("veya Garment URL", key="image_url")
195
-
196
  with c3:
197
  num_images = st.selectbox("Çıktı adedi", [1,2,3,4], index=0, key="num_images")
198
-
199
  with c4:
200
  custom_prompt = st.text_area("Özel prompt (boş bırak → varsayılan)", value="", height=80, key="custom_prompt")
201
 
@@ -203,16 +220,15 @@ bA, bB = st.columns([1.0, 1.0])
203
  with bA:
204
  st.info(f"Backend: {'Online' if ok else 'Offline'}", icon="🔌")
205
  with bB:
206
- # İki farklı çalıştırma seçeneği: sadece foto veya zincir
207
  run_image = st.button("Çalıştır (Sadece Foto)", type="primary", use_container_width=True, key="run_img_btn")
208
  run_chain = st.button("Zincir (Foto → Video hazırlık)", use_container_width=True, key="run_chain_btn")
209
 
210
  # ================= Demo Preview (mevcut klasörden) =================
211
  st.markdown("---")
212
  st.subheader("Demo preview (çalıştırmadan önce örnek)")
213
- st.caption("Bu bölüm sadece örnek; aynı klasörden **input.jpg** ve **tryon.jpg** okunur.")
214
 
215
- dp_in, dp_sp, dp_tp = st.columns(3)
216
  in_bytes = fetch_bytes("input.jpg")
217
  if in_bytes:
218
  dp_in.subheader("Input")
@@ -235,7 +251,12 @@ if try_bytes:
235
  else:
236
  show_tile(dp_sp, "Sample Output", None)
237
 
238
- show_tile(dp_tp, "Video (örnek yok)", None)
 
 
 
 
 
239
 
240
  # ================= Girdi Önizleme =================
241
  st.markdown("---")
@@ -297,12 +318,10 @@ if run_image or run_chain:
297
  image_json = out
298
  else:
299
  out = post_chain(form, files_payload) # to_video=false
300
- image_json = out.get("image_step") or out # Fallback
301
 
302
- # ---- Çıktıları çıkar ----
303
  imgs = (image_json.get("result") or {}).get("images") or []
304
  urls = [i.get("url") for i in imgs if isinstance(i, dict) and i.get("url")]
305
- # UI state
306
  st.session_state["job_counter"] += 1
307
  st.session_state["results"] = {
308
  "job_id": (image_json.get("job_id") or out.get("job_id")),
@@ -316,28 +335,35 @@ if run_image or run_chain:
316
  except Exception as e:
317
  st.error(f"Hata: {e}")
318
 
319
- # ================ Sonuçları Göster ================
320
  res = st.session_state.get("results") or {}
321
- vbytes = None
322
  if res:
323
  key_prefix = f"job{st.session_state['job_counter']}"
324
  img_urls = res.get("image_urls") or []
 
325
 
326
- # İlk 4 görseli göster
327
- cols = st.columns(4)
328
  named = []
329
- if img_urls:
330
- for idx in range(min(4, len(img_urls))):
331
- u = img_urls[idx]
332
- c = cols[idx] if idx < len(cols) else st
333
- title = "Look" if idx == 0 else f"Look #{idx+1}"
334
- _, b = show_tile(c, title, u, bg_rgb=white_bg, filename_stub=f"look_{idx+1}", key_prefix=f"{key_prefix}_{idx}")
335
- if b:
336
- named.append((f"look_{idx+1}{infer_ext(b)}", b))
 
 
 
 
 
 
337
  else:
338
- show_tile(cols[0], "Look", None)
 
339
 
340
- # ---- Video (ilk görselden) ----
341
  st.markdown("---")
342
  colv1, colv2, colv3 = st.columns([1.1, 1.0, 1.2])
343
  with colv1:
@@ -362,27 +388,13 @@ if res:
362
  vurl = (v.get("result") or {}).get("video", {}).get("url")
363
  if vurl:
364
  st.session_state["results"]["video_url"] = vurl
 
 
 
365
  else:
366
  st.info("Video URL gelmedi.")
367
 
368
- vurl = st.session_state["results"].get("video_url")
369
- if vurl:
370
- st.subheader("Video")
371
- st.video(vurl, format="video/mp4")
372
- vb = fetch_bytes(vurl)
373
- if vb:
374
- vbytes = vb
375
- st.download_button(
376
- "Video indir (MP4)",
377
- data=vb,
378
- file_name="fitstudio_video.mp4",
379
- mime="video/mp4",
380
- key=f"{key_prefix}_video_dl"
381
- )
382
- else:
383
- st.info("Video URL var ama içerik indirilemedi.")
384
-
385
- # ---- ZIP indir (isteğe bağlı) ----
386
  if named or vbytes:
387
  if vbytes:
388
  named.append(("video.mp4", vbytes))
 
1
  # streamlit_app.py — Fit Studio AI (Fashion & Apparel) v0.4 UI
2
  # Still Image (VTO) → (optional) Runway Video
3
+ # Demo preview: same folder "input.jpg" (girdi), "tryon.jpg" (örnek çıktı), "fitstudio_video.mp4" (örnek video)
4
 
5
  import os, io, zipfile, requests, streamlit as st
6
  from pathlib import Path
 
41
 
42
  # ================= Session State (ilk yük) =================
43
  defaults = {
44
+ "results": None,
45
+ "job_counter": 0,
46
+ "duration": "6",
47
  }
48
  for k, v in defaults.items():
49
  if k not in st.session_state:
 
137
  )
138
  return url, b
139
 
140
+ def show_video_tile(col, title, video_source: str | bytes | None, key_prefix=""):
141
+ col.subheader(title)
142
+ if not video_source:
143
+ col.caption("—")
144
+ return None
145
+ try:
146
+ if isinstance(video_source, (bytes, bytearray)):
147
+ col.video(video_source, format="video/mp4")
148
+ vb = video_source
149
+ else:
150
+ vb = fetch_bytes(video_source) if isinstance(video_source, str) else None
151
+ if vb:
152
+ col.video(vb, format="video/mp4")
153
+ if vb:
154
+ col.download_button("Video indir (MP4)", data=vb, file_name="fitstudio_video.mp4", mime="video/mp4",
155
+ key=f"{key_prefix}_video_dl")
156
+ return vb
157
+ except Exception:
158
+ col.info("Video yüklenemedi.")
159
+ return None
160
+
161
  def make_zip(named_bytes: list[tuple[str, bytes]]) -> bytes:
162
  buf = io.BytesIO()
163
  with zipfile.ZipFile(buf, "w", compression=zipfile.ZIP_DEFLATED) as z:
 
207
 
208
  with c0:
209
  category = st.selectbox("Kategori", ["general","underwear"], index=0, key="category")
 
210
  with c1:
211
  file_list = st.file_uploader("Garment image (upload)", type=["jpg","jpeg","png","webp"], accept_multiple_files=True, key="file_upl")
 
212
  with c2:
213
  image_url = st.text_input("veya Garment URL", key="image_url")
 
214
  with c3:
215
  num_images = st.selectbox("Çıktı adedi", [1,2,3,4], index=0, key="num_images")
 
216
  with c4:
217
  custom_prompt = st.text_area("Özel prompt (boş bırak → varsayılan)", value="", height=80, key="custom_prompt")
218
 
 
220
  with bA:
221
  st.info(f"Backend: {'Online' if ok else 'Offline'}", icon="🔌")
222
  with bB:
 
223
  run_image = st.button("Çalıştır (Sadece Foto)", type="primary", use_container_width=True, key="run_img_btn")
224
  run_chain = st.button("Zincir (Foto → Video hazırlık)", use_container_width=True, key="run_chain_btn")
225
 
226
  # ================= Demo Preview (mevcut klasörden) =================
227
  st.markdown("---")
228
  st.subheader("Demo preview (çalıştırmadan önce örnek)")
229
+ st.caption("Bu bölüm sadece örnek; aynı klasörden **input.jpg**, **tryon.jpg** ve **fitstudio_video.mp4** okunur.")
230
 
231
+ dp_in, dp_sp, dp_v = st.columns([1,1,1])
232
  in_bytes = fetch_bytes("input.jpg")
233
  if in_bytes:
234
  dp_in.subheader("Input")
 
251
  else:
252
  show_tile(dp_sp, "Sample Output", None)
253
 
254
+ demo_vbytes = fetch_bytes("fitstudio_video.mp4")
255
+ if demo_vbytes:
256
+ show_video_tile(dp_v, "Sample Video", demo_vbytes, key_prefix="demo")
257
+ else:
258
+ dp_v.subheader("Sample Video")
259
+ dp_v.caption("—")
260
 
261
  # ================= Girdi Önizleme =================
262
  st.markdown("---")
 
318
  image_json = out
319
  else:
320
  out = post_chain(form, files_payload) # to_video=false
321
+ image_json = out.get("image_step") or out
322
 
 
323
  imgs = (image_json.get("result") or {}).get("images") or []
324
  urls = [i.get("url") for i in imgs if isinstance(i, dict) and i.get("url")]
 
325
  st.session_state["job_counter"] += 1
326
  st.session_state["results"] = {
327
  "job_id": (image_json.get("job_id") or out.get("job_id")),
 
335
  except Exception as e:
336
  st.error(f"Hata: {e}")
337
 
338
+ # ================ Sonuçları Satırda Yan Yana Göster ================
339
  res = st.session_state.get("results") or {}
 
340
  if res:
341
  key_prefix = f"job{st.session_state['job_counter']}"
342
  img_urls = res.get("image_urls") or []
343
+ video_url = res.get("video_url")
344
 
345
+ # 1. Satır: 3 görsel + 1 video sütunu (video varsa göster)
346
+ c1, c2, c3, c4 = st.columns([1,1,1,1])
347
  named = []
348
+
349
+ # İlk 3 görsel
350
+ tiles = [c1, c2, c3]
351
+ for idx in range(min(3, len(img_urls))):
352
+ u = img_urls[idx]
353
+ title = "Look" if idx == 0 else f"Look #{idx+1}"
354
+ _, b = show_tile(tiles[idx], title, u, bg_rgb=white_bg, filename_stub=f"look_{idx+1}", key_prefix=f"{key_prefix}_{idx}")
355
+ if b:
356
+ named.append((f"look_{idx+1}{infer_ext(b)}", b))
357
+
358
+ # Video sütunu (küçük kadraj: sütun genişliği kadar)
359
+ vbytes = None
360
+ if video_url:
361
+ vbytes = show_video_tile(c4, "Video", video_url, key_prefix=key_prefix)
362
  else:
363
+ c4.subheader("Video")
364
+ c4.caption("Henüz üretilmedi.")
365
 
366
+ # 2. Satır: Video üretim kontrolleri (isteğe bağlı)
367
  st.markdown("---")
368
  colv1, colv2, colv3 = st.columns([1.1, 1.0, 1.2])
369
  with colv1:
 
388
  vurl = (v.get("result") or {}).get("video", {}).get("url")
389
  if vurl:
390
  st.session_state["results"]["video_url"] = vurl
391
+ video_url = vurl
392
+ # Hemen üst satırdaki sütuna küçük kadrajda göster
393
+ vbytes = show_video_tile(c4, "Video", video_url, key_prefix=key_prefix)
394
  else:
395
  st.info("Video URL gelmedi.")
396
 
397
+ # ZIP indir
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
398
  if named or vbytes:
399
  if vbytes:
400
  named.append(("video.mp4", vbytes))