Add 5 files
Browse files- README.md +21 -11
- README.mdfileyouneedtousethefollowing +5 -0
- app.js +52 -0
- index.html +1 -19
- style.css(TailwindCSS) +228 -0
README.md
CHANGED
@@ -1,11 +1,21 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<readme>
|
2 |
+
|
3 |
+
**Multitrack Audio Editor**
|
4 |
+
|
5 |
+
Multitrack Audio Editor is a simple audio editor built with wavesurfer.js and Alpine.js. It allows you to load multiple audio tracks, display the waveform, timeline, and playback controls. With the ability to mute/solo individual tracks, the user can mix and match audio to create a multitrack masterpiece.
|
6 |
+
|
7 |
+
## Preview
|
8 |
+
|
9 |
+
![Multitrack Audio Editor]("https://i.imgur.com/mLxOfQE.png")
|
10 |
+
|
11 |
+
## Features
|
12 |
+
|
13 |
+
* Load multiple audio tracks.
|
14 |
+
* Display waveform, timeline, and playback controls.
|
15 |
+
* Add mute/solo tracks features.
|
16 |
+
* Customizable design.
|
17 |
+
|
18 |
+
## Installation
|
19 |
+
|
20 |
+
1. Clone the repository
|
21 |
+
`git clone https://github.com/kcone42/multitrack-audio-editor.git`
|
README.mdfileyouneedtousethefollowing
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
npm run serve
|
2 |
+
|
3 |
+
npm run build
|
4 |
+
|
5 |
+
npm run test
|
app.js
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import WaveSurfer from 'https://cdn.jsdelivr.net/npm/[email protected]/dist/plugin/wavesurfer.multitrack.min.js'
|
2 |
+
import ThreeJs from 'https://cdnjs.cloudflare.com/ajax/libs/three.js/0.156.1/three.min.js'
|
3 |
+
import WaveSurferCanvas from 'https://www.npmjs.com/package/wavesurfer.js'
|
4 |
+
import TailwindTheme from 'https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio'
|
5 |
+
|
6 |
+
const wavesurfer = new WaveSurfer.create({
|
7 |
+
container: '#wavesurfer-container',
|
8 |
+
waveColor: '#69D2E7',
|
9 |
+
progressColor: '#69D2E7',
|
10 |
+
cursorColor: '#fff',
|
11 |
+
barHeight: 1,
|
12 |
+
cursorWidth: 0.1,
|
13 |
+
hideScrollbar: true,
|
14 |
+
})
|
15 |
+
|
16 |
+
const canvasEl = document.getElementById('wavesurfer-canvas')
|
17 |
+
const wavesurferCanvas = new WaveSurferCanvas(canvasEl, wavesurfer)
|
18 |
+
|
19 |
+
const threeJs = new ThreeJs.Scene()
|
20 |
+
const geometry = new ThreeJs.BoxGeometry(1, 1, 1)
|
21 |
+
const material = new ThreeJs.MeshBasicMaterial({ color: 0x00ff00 })
|
22 |
+
const cube = new ThreeJs.Mesh(geometry, material)
|
23 |
+
cube.position.z = -1
|
24 |
+
threeJs.add(cube)
|
25 |
+
|
26 |
+
const renderingElement = document.getElementById('rendering')
|
27 |
+
if (renderingElement) {
|
28 |
+
threeJs.renderingElement = renderingElement
|
29 |
+
renderingElement.appendChild(threeJs.canvas)
|
30 |
+
}
|
31 |
+
|
32 |
+
wavesurfer.on('ready', () => {
|
33 |
+
const soundSource = new ThreeJs.AudioDevice()
|
34 |
+
soundSource.setBuffer(wavesurferCanvas.wavesurfer.getSoundSource())
|
35 |
+
threeJs.add(soundSource)
|
36 |
+
soundSource.play()
|
37 |
+
})
|
38 |
+
|
39 |
+
const main = async () => {
|
40 |
+
await wavesurferCanvas.load(
|
41 |
+
'https://api.soundcloud.com/tracks/293'
|
42 |
+
)
|
43 |
+
wavesurfer.load('https://api.soundcloud.com/tracks/305')
|
44 |
+
document.body.style.display = 'flex'
|
45 |
+
document.body.style.flexDirection = 'column'
|
46 |
+
document.body.style.alignItems = 'center'
|
47 |
+
document.body.style.justifyContent = 'center'
|
48 |
+
document.body.style.height = `${wavesurfer.options.container.clientHeight}px`
|
49 |
+
document.body.style.width = `${wavesurfer.options.container.clientWidth}px`
|
50 |
+
}
|
51 |
+
|
52 |
+
main()
|
index.html
CHANGED
@@ -1,19 +1 @@
|
|
1 |
-
|
2 |
-
<html>
|
3 |
-
<head>
|
4 |
-
<meta charset="utf-8" />
|
5 |
-
<meta name="viewport" content="width=device-width" />
|
6 |
-
<title>My static Space</title>
|
7 |
-
<link rel="stylesheet" href="style.css" />
|
8 |
-
</head>
|
9 |
-
<body>
|
10 |
-
<div class="card">
|
11 |
-
<h1>Welcome to your static Space!</h1>
|
12 |
-
<p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
|
13 |
-
<p>
|
14 |
-
Also don't forget to check the
|
15 |
-
<a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
|
16 |
-
</p>
|
17 |
-
</div>
|
18 |
-
</body>
|
19 |
-
</html>
|
|
|
1 |
+
<html><head><link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/full.css" rel="stylesheet" type="text/css" /><script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script><script src="https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio"></script><script defer src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.156.1/three.min.js"></script><script type="module" src="main.js"></script><title>Multitrack Audio Editor</title></head><body><div class="wavesurfer-container"><div class="wavesurfer-multitrack"><canvas id="wavesurfer-canvas"></canvas></div></div><div class="timeline"></div><div class="controls"></div><div class="playback-controls"></div></body></html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
style.css(TailwindCSS)
ADDED
@@ -0,0 +1,228 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<<< erathemesruby-dark.css >>>
|
2 |
+
:root {
|
3 |
+
--green: #36B37E;
|
4 |
+
--green-dark: #58A19F;
|
5 |
+
--green-darker: #1D0606;
|
6 |
+
--green-light: #C9EDE5;
|
7 |
+
--blue: #3498db;
|
8 |
+
--blue-dark: #219ebc;
|
9 |
+
--blue-darker: #001f3f;
|
10 |
+
--red: #F2006A;
|
11 |
+
--red-dark: #001b4a;
|
12 |
+
--red-darker: #583ca9;
|
13 |
+
--gray: #CFD8DC;
|
14 |
+
}
|
15 |
+
|
16 |
+
checkbox,
|
17 |
+
label,
|
18 |
+
input,
|
19 |
+
textarea {
|
20 |
+
appearance: none;
|
21 |
+
box-sizing: border-box;
|
22 |
+
outline: none;
|
23 |
+
margin: 0;
|
24 |
+
padding: 0;
|
25 |
+
cursor: pointer;
|
26 |
+
}
|
27 |
+
|
28 |
+
button,
|
29 |
+
a {
|
30 |
+
appearance: none;
|
31 |
+
font-family: "Push";
|
32 |
+
font-size: 1rem;
|
33 |
+
border-radius: 4px;
|
34 |
+
box-shadow: 0 0 0 2px var(--none-color);
|
35 |
+
}
|
36 |
+
|
37 |
+
.button1,
|
38 |
+
.button2,
|
39 |
+
.button3 {
|
40 |
+
font-size: 1.2rem;
|
41 |
+
width: 300px;
|
42 |
+
height: 50px;
|
43 |
+
display: flex;
|
44 |
+
align-items: center;
|
45 |
+
justify-content: space-between;
|
46 |
+
color: #fff;
|
47 |
+
margin: 20px auto;
|
48 |
+
cursor: pointer;
|
49 |
+
background: linear-gradient(to right, var(--blue), var(--light-color));
|
50 |
+
}
|
51 |
+
|
52 |
+
.flex {
|
53 |
+
display: flex;
|
54 |
+
flex-wrap: wrap;
|
55 |
+
flex-direction: column;
|
56 |
+
align-items: center;
|
57 |
+
justify-content: center;
|
58 |
+
margin: 60px;
|
59 |
+
}
|
60 |
+
|
61 |
+
.buf {
|
62 |
+
margin: 20px;
|
63 |
+
}
|
64 |
+
|
65 |
+
.control {
|
66 |
+
height: 100%;
|
67 |
+
position: relative;
|
68 |
+
border: 1px solid rgb(123, 123, 123);
|
69 |
+
}
|
70 |
+
|
71 |
+
.control::after {
|
72 |
+
content: "";
|
73 |
+
position: absolute;
|
74 |
+
top: 50%;
|
75 |
+
left: 0;
|
76 |
+
width: 100%;
|
77 |
+
height: 10%;
|
78 |
+
background-color: #fff;
|
79 |
+
transform: translateY(-50%);
|
80 |
+
filter: brightness(1.5);
|
81 |
+
}
|
82 |
+
|
83 |
+
.track {
|
84 |
+
position: relative;
|
85 |
+
width: 100%;
|
86 |
+
height: 100%;
|
87 |
+
border: 1px solid rgb(123, 123, 123);
|
88 |
+
padding: 10px;
|
89 |
+
}
|
90 |
+
|
91 |
+
.track::after {
|
92 |
+
content: "";
|
93 |
+
position: absolute;
|
94 |
+
top: 0;
|
95 |
+
left: 0;
|
96 |
+
width: 100%;
|
97 |
+
height: 10px;
|
98 |
+
background-color: #fff;
|
99 |
+
z-index: 4;
|
100 |
+
}
|
101 |
+
|
102 |
+
.track::before {
|
103 |
+
content: "";
|
104 |
+
position: absolute;
|
105 |
+
top: 0;
|
106 |
+
left: 0;
|
107 |
+
width: 100%;
|
108 |
+
height: 100%;
|
109 |
+
background-color: #fff;
|
110 |
+
box-shadow: inset 0 0 20px #000;
|
111 |
+
z-index: 5;
|
112 |
+
filter: brightness(0.5);
|
113 |
+
}
|
114 |
+
|
115 |
+
.track.mute::after {
|
116 |
+
background-color: #eee;
|
117 |
+
}
|
118 |
+
|
119 |
+
.track.solo::after {
|
120 |
+
background-color: #eee;
|
121 |
+
}
|
122 |
+
|
123 |
+
.play {
|
124 |
+
position: absolute;
|
125 |
+
top: 50%;
|
126 |
+
left: 50%;
|
127 |
+
width: 10px;
|
128 |
+
height: 10px;
|
129 |
+
background-color: #fff;
|
130 |
+
border: 1px solid rgb(123, 123, 123);
|
131 |
+
z-index: 11;
|
132 |
+
box-shadow: inset 0 0 10px #000;
|
133 |
+
transform: translate(-50%, -50%);
|
134 |
+
}
|
135 |
+
|
136 |
+
.slider {
|
137 |
+
position: absolute;
|
138 |
+
top: 50%;
|
139 |
+
left: 50%;
|
140 |
+
width: 100%;
|
141 |
+
height: 10px;
|
142 |
+
margin-top: -5px;
|
143 |
+
transform: translate(-50%, -50%);
|
144 |
+
}
|
145 |
+
|
146 |
+
.slider::after {
|
147 |
+
content: "";
|
148 |
+
position: absolute;
|
149 |
+
top: 50%;
|
150 |
+
left: 0;
|
151 |
+
width: 100%;
|
152 |
+
height: 10px;
|
153 |
+
background-color: #fff;
|
154 |
+
z-index: 12;
|
155 |
+
box-shadow: inset 0 0 10px #000;
|
156 |
+
}
|
157 |
+
|
158 |
+
.slider::before {
|
159 |
+
content: "";
|
160 |
+
position: absolute;
|
161 |
+
top: 50%;
|
162 |
+
left: 50%;
|
163 |
+
width: 10px;
|
164 |
+
height: 10px;
|
165 |
+
background-color: #fff;
|
166 |
+
box-shadow: inset 0 0 10px #000;
|
167 |
+
transform: translate(-50%, -50%);
|
168 |
+
}
|
169 |
+
|
170 |
+
.mute,
|
171 |
+
.solo {
|
172 |
+
position: absolute;
|
173 |
+
top: 0;
|
174 |
+
left: 0;
|
175 |
+
width: 100%;
|
176 |
+
height: 100%;
|
177 |
+
background-color: #fff;
|
178 |
+
box-shadow: inset 0 0 20px #000;
|
179 |
+
z-index: 1;
|
180 |
+
}
|
181 |
+
|
182 |
+
.mute {
|
183 |
+
margin-bottom: 10px;
|
184 |
+
}
|
185 |
+
|
186 |
+
.solo {
|
187 |
+
margin-top: 10px;
|
188 |
+
}
|
189 |
+
|
190 |
+
.mute::after,
|
191 |
+
.solo::after {
|
192 |
+
content: "";
|
193 |
+
position: absolute;
|
194 |
+
top: 50%;
|
195 |
+
left: 0;
|
196 |
+
width: 100%;
|
197 |
+
height: 10px;
|
198 |
+
background-color: #fff;
|
199 |
+
z-index: 12;
|
200 |
+
box-shadow: inset 0 0 10px #000;
|
201 |
+
}
|
202 |
+
|
203 |
+
.mute::before,
|
204 |
+
.solo::before {
|
205 |
+
content: "";
|
206 |
+
position: absolute;
|
207 |
+
top: 50%;
|
208 |
+
left: 50%;
|
209 |
+
width: 10px;
|
210 |
+
height: 10px;
|
211 |
+
background-color: #fff;
|
212 |
+
box-shadow: inset 0 0 10px #000;
|
213 |
+
transform: translate(-50%, -50%);
|
214 |
+
}
|
215 |
+
|
216 |
+
.track.mute {
|
217 |
+
.slider,
|
218 |
+
.play {
|
219 |
+
background-color: red;
|
220 |
+
}
|
221 |
+
}
|
222 |
+
|
223 |
+
.track.solo {
|
224 |
+
.slider,
|
225 |
+
.play {
|
226 |
+
background-color: green;
|
227 |
+
}
|
228 |
+
}
|