seawolf2357 commited on
Commit
4bde71e
ยท
verified ยท
1 Parent(s): 12b1424

Update app-BACKUP2.py

Browse files
Files changed (1) hide show
  1. app-BACKUP2.py +80 -94
app-BACKUP2.py CHANGED
@@ -1,6 +1,7 @@
1
  """
2
  Simple Video Editor - Canvas ๊ธฐ๋ฐ˜ ๋ Œ๋”๋ง
3
  ๋นˆ ํ”„๋ ˆ์ž„ ๋ฌธ์ œ ์™„์ „ ํ•ด๊ฒฐ + ์„œ๋ฒ„ ์‚ฌ์ด๋“œ MP4 ๋‚ด๋ณด๋‚ด๊ธฐ
 
4
  """
5
 
6
  import gradio as gr
@@ -1007,25 +1008,28 @@ document.getElementById('exportMsg').textContent='๋…นํ™” ์ค€๋น„ ์ค‘...';
1007
  doExport();
1008
  }}
1009
 
 
 
 
1010
  async function doExport(){{
1011
  var size=S.ratioSizes[S.ratio];
1012
  var exportW=size.w,exportH=size.h;
1013
 
1014
- // ๋ฉ”์ธ ์บ”๋ฒ„์Šค (MediaRecorder ์—ฐ๊ฒฐ์šฉ)
1015
- var canvas=document.createElement('canvas');
1016
- canvas.width=exportW;canvas.height=exportH;
1017
- var ctx=canvas.getContext('2d');
1018
 
1019
- // ์˜คํ”„์Šคํฌ๋ฆฐ ์บ”๋ฒ„์Šค (๋ Œ๋”๋ง์šฉ - ๋”๋ธ” ๋ฒ„ํผ๋ง)
1020
  var offCanvas=document.createElement('canvas');
1021
  offCanvas.width=exportW;offCanvas.height=exportH;
1022
  var offCtx=offCanvas.getContext('2d');
1023
 
1024
  // ์ดˆ๊ธฐ ๊ฒ€์€ ํ™”๋ฉด
1025
- ctx.fillStyle='#000';
1026
- ctx.fillRect(0,0,exportW,exportH);
1027
 
1028
- var stream=canvas.captureStream(30);
1029
 
1030
  // ๊ณ ํ™”์งˆ ์„ค์ •
1031
  var opts={{mimeType:'video/webm;codecs=vp9',videoBitsPerSecond:8000000}};
@@ -1044,93 +1048,117 @@ document.getElementById('exportMsg').textContent='๋…นํ™” ์ค‘... ('+S.ratio+')';
1044
  rec.start(100);
1045
 
1046
  var dur=S.dur;
1047
- var fps=30;
1048
- var frameInterval=1000/fps;
1049
- var totalFrames=Math.ceil(dur*fps);
1050
- var startTime=performance.now();
1051
  var fillMode=S.fillMode;
1052
 
1053
- // ์‹ค์‹œ๊ฐ„ ๊ธฐ๋ฐ˜ ๋ Œ๋”๋ง
1054
- // ๋ธ”๋Ÿฌ ๋ชจ๋“œ์šฉ ํ”„๋ ˆ์ž„ ์บก์ฒ˜ ์บ”๋ฒ„์Šค (์žฌ์‚ฌ์šฉ)
1055
  var frameCanvas=document.createElement('canvas');
1056
- frameCanvas.width=1920;frameCanvas.height=1080;
1057
  var frameCtx=frameCanvas.getContext('2d');
 
 
 
1058
 
1059
- await new Promise(function(resolve){{
1060
- var frameCount=0;
1061
- var lastVideoEl=null;
1062
- var lastClipId=null;
 
 
 
 
 
1063
 
 
 
 
 
 
 
 
 
 
 
 
 
1064
  function render(){{
1065
  if(S.cancelled){{rec.stop();resolve();return}}
1066
 
1067
- var elapsed=performance.now()-startTime;
1068
- var t=elapsed/1000;
1069
-
1070
- if(t>=dur){{
1071
  rec.stop();
1072
- setTimeout(resolve,100);
1073
  return;
1074
  }}
1075
 
1076
- document.getElementById('exportBar').style.width=(t/dur*100)+'%';
1077
- document.getElementById('exportMsg').textContent='๋…นํ™” ์ค‘... '+Math.round(t/dur*100)+'% ('+t.toFixed(1)+'/'+dur.toFixed(1)+'์ดˆ)';
 
1078
 
 
1079
  offCtx.fillStyle='#000';
1080
  offCtx.fillRect(0,0,exportW,exportH);
1081
 
1082
- var vc=getClipAt(t,'visual');
1083
  if(vc){{
1084
  var el=S.els[vc.mid];
1085
  if(el){{
 
1086
  if(vc.type==='video'){{
1087
- var clipT=t-vc.start+vc.ts;
1088
- if(lastClipId!==vc.id){{
1089
- el.currentTime=clipT;
1090
- el.play().catch(function(){{}});
1091
- lastClipId=vc.id;
1092
- lastVideoEl=el;
1093
- }}
1094
- if(lastVideoEl&&lastVideoEl!==el&&!lastVideoEl.paused){{
1095
- lastVideoEl.pause();
1096
  }}
1097
- lastVideoEl=el;
1098
  }}
1099
 
1100
  try{{
1101
  var sw=el.videoWidth||el.naturalWidth||el.width||exportW;
1102
  var sh=el.videoHeight||el.naturalHeight||el.height||exportH;
1103
 
1104
- // ๋ธ”๋Ÿฌ ๋ชจ๋“œ: ํ”„๋ ˆ์ž„์„ ๋จผ์ € ์บก์ฒ˜
1105
  if(fillMode==='blur'){{
1106
- frameCanvas.width=sw;frameCanvas.height=sh;
 
 
1107
  frameCtx.drawImage(el,0,0,sw,sh);
1108
- drawBlurFromFrame(offCtx,frameCanvas,sw,sh,exportW,exportH);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1109
  }}else{{
1110
- drawWithModeExport(offCtx,el,sw,sh,exportW,exportH,fillMode);
1111
- }}
1112
- }}catch(e){{}}
 
1113
  }}
1114
- }}else{{
1115
- if(lastVideoEl&&!lastVideoEl.paused){{
1116
- lastVideoEl.pause();
1117
- lastClipId=null;
1118
  }}
1119
  }}
1120
 
1121
- // ํ…์ŠคํŠธ ์˜ค๋ฒ„๋ ˆ์ด ๋ Œ๋”๋ง
1122
- var textClips=getTextClipsAt(t);
1123
  textClips.forEach(function(tc){{
1124
  drawTextExport(offCtx,tc,exportW,exportH);
1125
  }});
1126
 
1127
- ctx.drawImage(offCanvas,0,0);
 
 
1128
  requestAnimationFrame(render);
1129
  }}
1130
-
1131
  requestAnimationFrame(render);
1132
  }});
1133
 
 
1134
  Object.keys(S.els).forEach(function(k){{
1135
  var el=S.els[k];
1136
  if(el&&el.pause)el.pause();
@@ -1175,48 +1203,6 @@ downloadDiv.appendChild(copyBtn);
1175
  document.querySelector('.modal-box').appendChild(downloadDiv);
1176
  }}
1177
 
1178
- // ๋‚ด๋ณด๋‚ด๊ธฐ์šฉ ๊ทธ๋ฆฌ๊ธฐ ํ•จ์ˆ˜ (๋ธ”๋Ÿฌ ํšจ๊ณผ ํฌํ•จ)
1179
- function drawWithModeExport(ctx,el,sw,sh,dw,dh,mode){{
1180
- if(mode==='fill'){{
1181
- var scale=Math.max(dw/sw,dh/sh);
1182
- var nw=sw*scale,nh=sh*scale;
1183
- var ox=(dw-nw)/2,oy=(dh-nh)/2;
1184
- ctx.drawImage(el,ox,oy,nw,nh);
1185
- }}else{{
1186
- var scale=Math.min(dw/sw,dh/sh);
1187
- var nw=sw*scale,nh=sh*scale;
1188
- var ox=(dw-nw)/2,oy=(dh-nh)/2;
1189
- ctx.drawImage(el,ox,oy,nw,nh);
1190
- }}
1191
- }}
1192
-
1193
- // ๋ธ”๋Ÿฌ ์ „์šฉ - ์บก์ฒ˜๋œ ํ”„๋ ˆ์ž„์œผ๋กœ ์ฒ˜๋ฆฌ
1194
- function drawBlurFromFrame(ctx,frameCanvas,sw,sh,dw,dh){{
1195
- // 1. ์ž‘์€ ์บ”๋ฒ„์Šค๋กœ ์ถ•์†Œ (๋ธ”๋Ÿฌ ํšจ๊ณผ)
1196
- var blurCanvas=document.createElement('canvas');
1197
- blurCanvas.width=16;blurCanvas.height=16;
1198
- var blurCtx=blurCanvas.getContext('2d');
1199
- blurCtx.drawImage(frameCanvas,0,0,16,16);
1200
-
1201
- // 2. ๋ฐฐ๊ฒฝ์— ํ™•๋Œ€ํ•ด์„œ ๊ทธ๋ฆผ
1202
- ctx.imageSmoothingEnabled=true;
1203
- ctx.imageSmoothingQuality='high';
1204
- var scale=Math.max(dw/sw,dh/sh)*1.1;
1205
- var nw=sw*scale,nh=sh*scale;
1206
- var ox=(dw-nw)/2,oy=(dh-nh)/2;
1207
- ctx.drawImage(blurCanvas,ox,oy,nw,nh);
1208
-
1209
- // 3. ์–ด๋‘ก๊ฒŒ
1210
- ctx.fillStyle='rgba(0,0,0,0.4)';
1211
- ctx.fillRect(0,0,dw,dh);
1212
-
1213
- // 4. ์›๋ณธ (์บก์ฒ˜๋œ ํ”„๋ ˆ์ž„ ์‚ฌ์šฉ)
1214
- var fitScale=Math.min(dw/sw,dh/sh);
1215
- var fw=sw*fitScale,fh=sh*fitScale;
1216
- var fx=(dw-fw)/2,fy=(dh-fh)/2;
1217
- ctx.drawImage(frameCanvas,fx,fy,fw,fh);
1218
- }}
1219
-
1220
  // ๋‚ด๋ณด๋‚ด๊ธฐ์šฉ ํ…์ŠคํŠธ ๋ Œ๋”๋ง
1221
  function drawTextExport(ctx,clip,dw,dh){{
1222
  var text=clip.text;
@@ -1450,7 +1436,7 @@ def convert_webm_to_mp4(webm_base64):
1450
  return None
1451
 
1452
  with gr.Blocks() as demo:
1453
- gr.Markdown("## ๐ŸŽฌ Video Editor")
1454
 
1455
  f = gr.File(label="๐Ÿ“ ํŒŒ์ผ ์—…๋กœ๋“œ", file_count="multiple", file_types=["video", "image", "audio"])
1456
  e = gr.HTML(value=make_iframe([]))
 
1
  """
2
  Simple Video Editor - Canvas ๊ธฐ๋ฐ˜ ๋ Œ๋”๋ง
3
  ๋นˆ ํ”„๋ ˆ์ž„ ๋ฌธ์ œ ์™„์ „ ํ•ด๊ฒฐ + ์„œ๋ฒ„ ์‚ฌ์ด๋“œ MP4 ๋‚ด๋ณด๋‚ด๊ธฐ
4
+ ๋ธ”๋Ÿฌ ๋ฐฐ๊ฒฝ ๋‚ด๋ณด๋‚ด๊ธฐ ์ˆ˜์ •: ๋”๋ธ” ๋ฒ„ํผ๋ง
5
  """
6
 
7
  import gradio as gr
 
1008
  doExport();
1009
  }}
1010
 
1011
+ // ============================================
1012
+ // ํ•ต์‹ฌ ์ˆ˜์ •: ๋”๋ธ” ๋ฒ„ํผ๋ง์œผ๋กœ ๋ธ”๋Ÿฌ ๋ฒˆ์ฉ์ž„ ๋ฐฉ์ง€
1013
+ // ============================================
1014
  async function doExport(){{
1015
  var size=S.ratioSizes[S.ratio];
1016
  var exportW=size.w,exportH=size.h;
1017
 
1018
+ // โ˜… ๋ฉ”์ธ ์บ”๋ฒ„์Šค (MediaRecorder ์—ฐ๊ฒฐ) - ์™„์„ฑ๋œ ํ”„๋ ˆ์ž„๋งŒ ๋ฐ›์Œ
1019
+ var mainCanvas=document.createElement('canvas');
1020
+ mainCanvas.width=exportW;mainCanvas.height=exportH;
1021
+ var mainCtx=mainCanvas.getContext('2d');
1022
 
1023
+ // โ˜… ์˜คํ”„์Šคํฌ๋ฆฐ ์บ”๋ฒ„์Šค (๋ Œ๋”๋ง์šฉ) - ์—ฌ๊ธฐ์„œ ๋ชจ๋“  ์ž‘์—… ํ›„ ํ•œ๋ฒˆ์— ๋ณต์‚ฌ
1024
  var offCanvas=document.createElement('canvas');
1025
  offCanvas.width=exportW;offCanvas.height=exportH;
1026
  var offCtx=offCanvas.getContext('2d');
1027
 
1028
  // ์ดˆ๊ธฐ ๊ฒ€์€ ํ™”๋ฉด
1029
+ mainCtx.fillStyle='#000';
1030
+ mainCtx.fillRect(0,0,exportW,exportH);
1031
 
1032
+ var stream=mainCanvas.captureStream(30);
1033
 
1034
  // ๊ณ ํ™”์งˆ ์„ค์ •
1035
  var opts={{mimeType:'video/webm;codecs=vp9',videoBitsPerSecond:8000000}};
 
1048
  rec.start(100);
1049
 
1050
  var dur=S.dur;
 
 
 
 
1051
  var fillMode=S.fillMode;
1052
 
1053
+ // ๋ธ”๋Ÿฌ์šฉ ์บ”๋ฒ„์Šค (์žฌ์‚ฌ์šฉ)
 
1054
  var frameCanvas=document.createElement('canvas');
 
1055
  var frameCtx=frameCanvas.getContext('2d');
1056
+ var blurCanvas=document.createElement('canvas');
1057
+ blurCanvas.width=16;blurCanvas.height=16;
1058
+ var blurCtx=blurCanvas.getContext('2d');
1059
 
1060
+ // ๋ชจ๋“  ๋น„๋””์˜ค๋ฅผ ์ฒ˜์Œ์œผ๋กœ ๋˜๋Œ๋ฆฌ๊ณ  ์žฌ์ƒ
1061
+ var videoClips=S.clips.filter(function(c){{return c.type==='video'}});
1062
+ videoClips.forEach(function(vc){{
1063
+ var el=S.els[vc.mid];
1064
+ if(el){{
1065
+ el.currentTime=vc.ts;
1066
+ el.muted=true;
1067
+ }}
1068
+ }});
1069
 
1070
+ // ์ž ์‹œ ๋Œ€๊ธฐ ํ›„ ์žฌ์ƒ ์‹œ์ž‘
1071
+ await new Promise(function(r){{setTimeout(r,200)}});
1072
+
1073
+ videoClips.forEach(function(vc){{
1074
+ var el=S.els[vc.mid];
1075
+ if(el)el.play().catch(function(){{}});
1076
+ }});
1077
+
1078
+ var startTime=performance.now();
1079
+
1080
+ // ์‹ค์‹œ๊ฐ„ ๋ Œ๋”๋ง ๋ฃจํ”„
1081
+ await new Promise(function(resolve){{
1082
  function render(){{
1083
  if(S.cancelled){{rec.stop();resolve();return}}
1084
 
1085
+ var elapsed=(performance.now()-startTime)/1000;
1086
+ if(elapsed>=dur){{
 
 
1087
  rec.stop();
1088
+ setTimeout(resolve,200);
1089
  return;
1090
  }}
1091
 
1092
+ // ์ง„ํ–‰๋ฅ  ์—…๋ฐ์ดํŠธ
1093
+ document.getElementById('exportBar').style.width=(elapsed/dur*100)+'%';
1094
+ document.getElementById('exportMsg').textContent='๋…นํ™” ์ค‘... '+Math.round(elapsed/dur*100)+'%';
1095
 
1096
+ // โ˜… ์˜คํ”„์Šคํฌ๋ฆฐ ์บ”๋ฒ„์Šค์— ์™„์ „ํžˆ ๋ Œ๋”๋ง โ˜…
1097
  offCtx.fillStyle='#000';
1098
  offCtx.fillRect(0,0,exportW,exportH);
1099
 
1100
+ var vc=getClipAt(elapsed,'visual');
1101
  if(vc){{
1102
  var el=S.els[vc.mid];
1103
  if(el){{
1104
+ // ๋น„๋””์˜ค ์‹œ๊ฐ„ ๋™๊ธฐํ™” (์ฐจ์ด๊ฐ€ ํฌ๋ฉด ๋ณด์ •)
1105
  if(vc.type==='video'){{
1106
+ var targetT=elapsed-vc.start+vc.ts;
1107
+ if(Math.abs(el.currentTime-targetT)>0.5){{
1108
+ el.currentTime=targetT;
 
 
 
 
 
 
1109
  }}
 
1110
  }}
1111
 
1112
  try{{
1113
  var sw=el.videoWidth||el.naturalWidth||el.width||exportW;
1114
  var sh=el.videoHeight||el.naturalHeight||el.height||exportH;
1115
 
 
1116
  if(fillMode==='blur'){{
1117
+ // โ˜… ๋ธ”๋Ÿฌ: ์˜คํ”„์Šคํฌ๋ฆฐ์—์„œ ์™„์ „ํžˆ ์ฒ˜๋ฆฌ ํ›„ ๋ฉ”์ธ์— ๋ณต์‚ฌ โ˜…
1118
+ frameCanvas.width=sw;
1119
+ frameCanvas.height=sh;
1120
  frameCtx.drawImage(el,0,0,sw,sh);
1121
+ blurCtx.drawImage(frameCanvas,0,0,16,16);
1122
+
1123
+ offCtx.imageSmoothingEnabled=true;
1124
+ offCtx.imageSmoothingQuality='high';
1125
+ var scale=Math.max(exportW/sw,exportH/sh)*1.1;
1126
+ var nw=sw*scale,nh=sh*scale;
1127
+ offCtx.drawImage(blurCanvas,(exportW-nw)/2,(exportH-nh)/2,nw,nh);
1128
+ offCtx.fillStyle='rgba(0,0,0,0.4)';
1129
+ offCtx.fillRect(0,0,exportW,exportH);
1130
+ var fitScale=Math.min(exportW/sw,exportH/sh);
1131
+ var fw=sw*fitScale,fh=sh*fitScale;
1132
+ offCtx.drawImage(frameCanvas,(exportW-fw)/2,(exportH-fh)/2,fw,fh);
1133
+ }}else if(fillMode==='fill'){{
1134
+ var scale=Math.max(exportW/sw,exportH/sh);
1135
+ var nw=sw*scale,nh=sh*scale;
1136
+ offCtx.drawImage(el,(exportW-nw)/2,(exportH-nh)/2,nw,nh);
1137
  }}else{{
1138
+ // fit
1139
+ var scale=Math.min(exportW/sw,exportH/sh);
1140
+ var nw=sw*scale,nh=sh*scale;
1141
+ offCtx.drawImage(el,(exportW-nw)/2,(exportH-nh)/2,nw,nh);
1142
  }}
1143
+ }}catch(e){{console.error('Draw error:',e)}}
 
 
 
1144
  }}
1145
  }}
1146
 
1147
+ // ํ…์ŠคํŠธ ์˜ค๋ฒ„๋ ˆ์ด ๋ Œ๋”๋ง (์˜คํ”„์Šคํฌ๋ฆฐ์—)
1148
+ var textClips=getTextClipsAt(elapsed);
1149
  textClips.forEach(function(tc){{
1150
  drawTextExport(offCtx,tc,exportW,exportH);
1151
  }});
1152
 
1153
+ // โ˜… ์˜คํ”„์Šคํฌ๋ฆฐ โ†’ ๋ฉ”์ธ ์บ”๋ฒ„์Šค๋กœ ํ•œ๋ฒˆ์— ๋ณต์‚ฌ (atomic) โ˜…
1154
+ mainCtx.drawImage(offCanvas,0,0);
1155
+
1156
  requestAnimationFrame(render);
1157
  }}
 
1158
  requestAnimationFrame(render);
1159
  }});
1160
 
1161
+ // ์ •๋ฆฌ
1162
  Object.keys(S.els).forEach(function(k){{
1163
  var el=S.els[k];
1164
  if(el&&el.pause)el.pause();
 
1203
  document.querySelector('.modal-box').appendChild(downloadDiv);
1204
  }}
1205
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1206
  // ๋‚ด๋ณด๋‚ด๊ธฐ์šฉ ํ…์ŠคํŠธ ๋ Œ๋”๋ง
1207
  function drawTextExport(ctx,clip,dw,dh){{
1208
  var text=clip.text;
 
1436
  return None
1437
 
1438
  with gr.Blocks() as demo:
1439
+ gr.Markdown("## ๐ŸŽฌ Video Editor (๋ธ”๋Ÿฌ ์ˆ˜์ •)")
1440
 
1441
  f = gr.File(label="๐Ÿ“ ํŒŒ์ผ ์—…๋กœ๋“œ", file_count="multiple", file_types=["video", "image", "audio"])
1442
  e = gr.HTML(value=make_iframe([]))