그동안 쌓여 있던 미커밋 파일들을 정리. 소스·자산만 올리고, 개인 데이터와 런타임 상태는 gitignore로 차단. 추가된 자산: - web-ui/audiomass, web-ui/wavacity — 자체 호스팅 오디오 에디터 - web-ui/drums — 드럼 샘플 - wol-gate — WOL 프록시 컨테이너(Dockerfile + server.js) - glm-1m-fix — GLM 1M 컨텍스트 설치 스크립트(linux/windows) - RENODE_FIXES_SUMMARY*.md, CCTV정보_서울특별시.csv, .claude/plans 수정: - edge_tts_synth.py: rate 인자 추가(말하기 속도 조절) - .smallclaw/config.json: google(gemini) provider 등록 — 키는 vault 참조 - assets/SmallClaw*.png 삭제분 반영 gitignore (중요): - .smallclaw/users/*/workspace/ 전체 차단. 기존 패턴이 memory/uploads와 일부 확장자만 막아서 detective/(고소장·통화녹취·의사소견서·가족관계증명서), generated-media/, music/, pptx/ 등 앱 생성 개인 데이터 403MB가 노출돼 있었음 - .smallclaw/active-sessions.json 차단 — 살아있는 bearer 토큰과 admin 역할이 평문으로 들어있어 커밋 시 게이트웨이 관리자 자격증명이 그대로 공개됨 - google-usage.json, config.json.bak-*, workspace/memory·weather-maps· task_result_*, voice/ 등 런타임 상태도 함께 차단 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
301 lines
6.8 KiB
HTML
301 lines
6.8 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<script>window.update = function(){};</script>
|
|
|
|
<title>AudioMass - Spectrum Analyzer</title>
|
|
<style>
|
|
html,body{height:100%}
|
|
body{padding:0;margin:0;background:#111;position:relative;z-index:2;overflow:hidden;}
|
|
div{position:absolute;top:50%;left:0;right:0;z-index:1;margin-top:-18px;text-align:center;user-select:none;
|
|
font-size:28px;color:#191919;pointer-events:none;opacity:.75;font-family:Arial}
|
|
#e, #d, #f{
|
|
cursor:pointer;
|
|
position: absolute;
|
|
top: 7px;
|
|
right: 7px;
|
|
display: block;
|
|
height: 20px;
|
|
z-index: 99999;
|
|
background: #eaeaea;
|
|
left:auto;
|
|
border-radius:4px;
|
|
color:#111;
|
|
font:9px/20px Arial,sans-serif;
|
|
width: auto;
|
|
padding: 0 6px;
|
|
text-align: center;
|
|
opacity:0.9;
|
|
user-select:none;
|
|
}
|
|
|
|
.b #e, .b #d{
|
|
top:12px;
|
|
}
|
|
|
|
#d{
|
|
min-width:40px;
|
|
}
|
|
|
|
.b #e, .b #f{
|
|
display:block;
|
|
}
|
|
|
|
#e{
|
|
right: 68px;
|
|
width: 10px;
|
|
line-height: 20px;
|
|
padding: 0px 6px;
|
|
text-align: center;
|
|
opacity: 0.9;
|
|
display:none;
|
|
}
|
|
|
|
#f{
|
|
left: 0;
|
|
right: 0;
|
|
top: 0;
|
|
padding: 0;
|
|
width: 100%;
|
|
line-height: 0;
|
|
border-radius: 0;
|
|
height: 4px;
|
|
background: #333;
|
|
display:none;
|
|
user-select:none;
|
|
-moz-user-select:none;
|
|
}
|
|
|
|
.c #f, #f:hover{
|
|
background:#3C3C3C;
|
|
}
|
|
|
|
</style>
|
|
<meta charset="utf-8" />
|
|
</head>
|
|
<body>
|
|
<canvas id="fr" width="600" height="188" style="width:100%;height:100%;display:block"></canvas>
|
|
<div>SPECTRUM ANALYSER</div>
|
|
|
|
<a id="d" onclick="dock()">DOCK</a>
|
|
<a id="e" onclick="remove()">X</a>
|
|
<a id="f" onmousedown="drag(event)"></a>
|
|
|
|
<script>
|
|
var d = document;
|
|
var w = window;
|
|
var iframe = location.href.indexOf('?iframe') === -1 ? 0 : 1;
|
|
var canvas = d.getElementById('fr');
|
|
var ctx = canvas.getContext('2d', {alpha:true, antialias:false});
|
|
|
|
w.remove = function (){};
|
|
if (iframe) {
|
|
d.body.className = 'b';
|
|
d.getElementById ('d').textContent = 'UNDOCK';
|
|
w.remove = function () {
|
|
w.parent.PKAudioEditor.ui.Dock ('RequestShowFreqAn', 'sp', [1, 1]);
|
|
};
|
|
};
|
|
|
|
w.drag = function ( e ) {
|
|
e.preventDefault ();
|
|
e.stopPropagation ();
|
|
|
|
w.parent.PKAudioEditor.ui.Dock ('RequestDragI', 'sp', [e.screenX, e.screenY]);
|
|
};
|
|
|
|
w.dock = function () {
|
|
if (!iframe)
|
|
{
|
|
if (!w.opener || !w.opener.PKAudioEditor) {
|
|
return ;
|
|
}
|
|
|
|
w.opener.PKAudioEditor.ui.Dock ('RequestShowFreqAn', 'sp', [1, 1]);
|
|
w.close && w.close ();
|
|
}
|
|
else
|
|
{
|
|
var frm = w.parent.document.getElementById ('pk_fr' + 'sp');
|
|
var t = 1;
|
|
|
|
if (frm && frm.getBoundingClientRect) {
|
|
var rect = frm.getBoundingClientRect ();
|
|
t = [(w.parent.screenLeft + rect.left + 100)||0, (w.parent.screenTop + rect.top + 25)||0];
|
|
}
|
|
|
|
w.parent.PKAudioEditor.ui.Dock ('RequestShowFreqAn', 'sp', [t, 0]);
|
|
}
|
|
};
|
|
|
|
w.getGrayColor = function(value) {
|
|
return 'rgb(V, V, V)'.replace(/V/g, 255 - value);
|
|
};
|
|
|
|
w.getFullColor = function(value) {
|
|
var colorPalette = {
|
|
0: [0,0,0],
|
|
10: [75, 0, 159],
|
|
20: [104,0,251],
|
|
30: [131,0,255],
|
|
40: [155,18,157],
|
|
50: [175, 37, 0],
|
|
60: [191, 59, 0],
|
|
70: [206, 88, 0],
|
|
80: [223, 132, 0],
|
|
90: [240, 188, 0],
|
|
100: [255, 252, 0]
|
|
};
|
|
|
|
//floor to nearest 10:
|
|
var decimalised = 100 * value / 255
|
|
var percent = decimalised / 100;
|
|
var floored = 10* Math.floor(decimalised / 10);
|
|
var distFromFloor = decimalised - floored;
|
|
var distFromFloorPercentage = distFromFloor/10;
|
|
var rangeToNextColor;
|
|
|
|
if (decimalised < 100){
|
|
rangeToNextColor = [
|
|
colorPalette[floored + 10][0] - colorPalette[floored + 10][0],
|
|
colorPalette[floored + 10][1] - colorPalette[floored + 10][1],
|
|
colorPalette[floored + 10][2] - colorPalette[floored + 10][2]
|
|
];
|
|
} else {
|
|
rangeToNextColor = [0,0,0];
|
|
}
|
|
|
|
var color = [
|
|
colorPalette[floored][0] + distFromFloorPercentage * rangeToNextColor[0],
|
|
colorPalette[floored][1] + distFromFloorPercentage * rangeToNextColor[1],
|
|
colorPalette[floored][2] + distFromFloorPercentage * rangeToNextColor[2]
|
|
];
|
|
|
|
return "rgb(" + color[0] +", "+color[1] +"," + color[2]+")";
|
|
};
|
|
|
|
setTimeout(function () {
|
|
if (!iframe)
|
|
{
|
|
if (!w.opener || !w.opener.PKAudioEditor) return ;
|
|
}
|
|
|
|
var WIDTH = w.innerWidth, HEIGHT = w.innerHeight;
|
|
|
|
if (canvas.width != WIDTH)
|
|
{
|
|
canvas.width = WIDTH;
|
|
canvas.height = HEIGHT;
|
|
}
|
|
|
|
var bufferLength = 240;
|
|
var value_changed = false;
|
|
var speed = 3;
|
|
|
|
var tempCanvas = document.createElement('canvas');
|
|
tempCanvas.width = WIDTH;
|
|
tempCanvas.height = HEIGHT;
|
|
|
|
// console.log(this.canvas.height, this.tempCanvas.height);
|
|
var tempCtx = tempCanvas.getContext ('2d');
|
|
|
|
ctx.clearRect (0, 0, WIDTH, HEIGHT);
|
|
|
|
function draw( data ) {
|
|
|
|
var WIDTH = window.innerWidth, HEIGHT = window.innerHeight;
|
|
|
|
if (canvas.width != WIDTH || canvas.height != HEIGHT)
|
|
{
|
|
canvas.width = WIDTH;
|
|
canvas.height = HEIGHT;
|
|
tempCanvas.width = WIDTH;
|
|
tempCanvas.height = HEIGHT;
|
|
}
|
|
|
|
tempCtx.drawImage (canvas, 0, 0, WIDTH, HEIGHT);
|
|
|
|
ctx.fillStyle = 'rgb(0, 0, 0)';
|
|
ctx.fillRect(0, 0, WIDTH, HEIGHT);
|
|
|
|
// Iterate over the frequencies.
|
|
for (var i = 0; i < data.length; ++i)
|
|
{
|
|
var value;
|
|
// Draw each pixel with the specific color.
|
|
// if (this.log) {
|
|
// logIndex = this.logScale(i, data.length);
|
|
// value = data[logIndex];
|
|
// } else {
|
|
value = data[i];
|
|
// }
|
|
|
|
ctx.fillStyle = window.getFullColor(value);
|
|
|
|
var percent = i / data.length;
|
|
var y = Math.round (percent * HEIGHT);
|
|
|
|
// draw the line at the right side of the canvas
|
|
ctx.fillRect(WIDTH - speed, HEIGHT - y,
|
|
speed, speed);
|
|
}
|
|
|
|
// Translate the canvas.
|
|
ctx.translate(-speed, 0);
|
|
// Draw the copied image.
|
|
// console.log(this.width, this.height);
|
|
ctx.drawImage (tempCanvas, 0, 0, WIDTH, HEIGHT,
|
|
0, 0, WIDTH, HEIGHT);
|
|
|
|
// Reset the transformation matrix.
|
|
ctx.setTransform (1, 0, 0, 1, 0, 0);
|
|
|
|
value_changed = false;
|
|
};
|
|
w.draw = draw;
|
|
|
|
w.onunload = function () {
|
|
w.destroy && w.destroy ( iframe );
|
|
w.destroy = null;
|
|
};
|
|
|
|
w.update = function (freq_arr) {
|
|
if (!freq_arr)
|
|
ctx.clearRect (0, 0, WIDTH, HEIGHT);
|
|
else {
|
|
if (value_changed) return ;
|
|
value_changed = true;
|
|
|
|
window.requestAnimationFrame(function () {
|
|
draw (freq_arr);
|
|
});
|
|
}
|
|
};
|
|
|
|
var last_press = 0;
|
|
document.addEventListener ('keypress', function ( e ) {
|
|
if (e.keyCode !== 32) return ;
|
|
|
|
e.preventDefault ();
|
|
e.stopPropagation ();
|
|
|
|
if (e.timeStamp - last_press < 100) {
|
|
return ;
|
|
}
|
|
|
|
last_press = e.timeStamp;
|
|
|
|
if (!iframe) {
|
|
w.opener && w.opener.PKAudioEditor.ui.Dock ('RequestKeyDown', 32);
|
|
}
|
|
else {
|
|
w.parent && w.parent.PKAudioEditor.ui.Dock ('RequestKeyDown', 32);
|
|
}
|
|
});
|
|
|
|
}, 60);
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|