start of react migration
This commit is contained in:
235
electron-ui/src/renderer/components/AudioTrimer.tsx
Normal file
235
electron-ui/src/renderer/components/AudioTrimer.tsx
Normal file
@ -0,0 +1,235 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
// import WaveSurfer from 'wavesurfer.js';
|
||||
import Regions from 'wavesurfer.js/dist/plugins/regions.esm.js';
|
||||
// import { useWavesurfer } from '@wavesurfer/react';
|
||||
import { BlockList } from 'net';
|
||||
|
||||
import WavesurferPlayer from '@wavesurfer/react';
|
||||
// import { IpcRenderer } from 'electron';
|
||||
|
||||
export interface AudioTrimmerProps {
|
||||
filePath: string;
|
||||
section: string;
|
||||
title?: string;
|
||||
trimStart?: number;
|
||||
trimEnd?: number;
|
||||
onSave?: (trimStart: number, trimEnd: number, title?: string) => void;
|
||||
onDelete?: () => void;
|
||||
}
|
||||
|
||||
function getBaseName(filePath: string) {
|
||||
return filePath.split(/[\\/]/).pop() || filePath;
|
||||
}
|
||||
|
||||
export default function AudioTrimmer({ filePath }: { filePath: string }) {
|
||||
const [blobUrl, setBlobUrl] = useState<string | undefined>(undefined);
|
||||
const [wavesurfer, setWavesurfer] = useState(null);
|
||||
const [isPlaying, setIsPlaying] = useState(false);
|
||||
|
||||
const plugins = useMemo(() => {
|
||||
return [Regions.create()];
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
let url: string | null = null;
|
||||
async function fetchAudio() {
|
||||
// console.log('Loading audio buffer for file:', filePath);
|
||||
const buffer =
|
||||
await window.electron.ipcRenderer.loadAudioBuffer(filePath);
|
||||
if (buffer && !buffer.error) {
|
||||
const audioData = buffer.data ? new Uint8Array(buffer.data) : buffer;
|
||||
url = URL.createObjectURL(new Blob([audioData]));
|
||||
setBlobUrl(url);
|
||||
console.log('Audio blob URL created:', url);
|
||||
}
|
||||
}
|
||||
fetchAudio();
|
||||
return () => {
|
||||
if (url) URL.revokeObjectURL(url);
|
||||
};
|
||||
}, [filePath]);
|
||||
|
||||
const onReady = (ws) => {
|
||||
setWavesurfer(ws);
|
||||
setIsPlaying(false);
|
||||
// setDuration(ws.getDuration());
|
||||
// console.log('Wavesurfer ready, duration:', ws.getDuration());
|
||||
// console.log('Wavesurfer regions plugin:', ws.plugins[0]);
|
||||
ws.plugins[0].addRegion?.({
|
||||
start: 0,
|
||||
end: ws.getDuration(),
|
||||
color: 'rgba(132, 81, 224, 0.3)',
|
||||
drag: false,
|
||||
resize: true,
|
||||
});
|
||||
};
|
||||
|
||||
const onPlayPause = () => {
|
||||
if (wavesurfer === null) return;
|
||||
wavesurfer.playPause();
|
||||
};
|
||||
|
||||
// useEffect(() => {
|
||||
// if (!containerRef.current || !blobUrl) return;
|
||||
// const ws = WaveSurfer.create({
|
||||
// container: containerRef.current,
|
||||
// waveColor: 'purple',
|
||||
// url: blobUrl,
|
||||
// height: 100,
|
||||
// width: 600,
|
||||
// });
|
||||
// return () => ws.destroy();
|
||||
// }, [blobUrl]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* <div ref={containerRef} /> */}
|
||||
<WavesurferPlayer
|
||||
height={100}
|
||||
width={600}
|
||||
url={blobUrl}
|
||||
onReady={onReady}
|
||||
onPlay={() => setIsPlaying(true)}
|
||||
onPause={() => setIsPlaying(false)}
|
||||
plugins={plugins}
|
||||
/>
|
||||
<button type="button" onClick={onPlayPause}>
|
||||
{isPlaying ? 'Pause' : 'Play'}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// export default function AudioTrimmer({
|
||||
// filePath,
|
||||
// section,
|
||||
// title,
|
||||
// trimStart = 0,
|
||||
// trimEnd,
|
||||
// onSave,
|
||||
// onDelete,
|
||||
// }: AudioTrimmerProps) {
|
||||
// const [wavesurfer, setWavesurfer] = useState(null);
|
||||
// const waveformRef = useRef<HTMLDivElement>(null);
|
||||
// const wavesurferRef = useRef<WaveSurfer | null>(null);
|
||||
// const [region, setRegion] = useState<{ start: number; end: number }>({
|
||||
// start: trimStart,
|
||||
// end: trimEnd || 0,
|
||||
// });
|
||||
// // eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
// const [duration, setDuration] = useState<number>(0);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (!waveformRef.current) return;
|
||||
|
||||
// // const regions = Regions.create({
|
||||
// // color: 'rgba(132, 81, 224, 0.3)',
|
||||
// // drag: false,
|
||||
// // resize: true,
|
||||
// // });
|
||||
|
||||
// const regions = Regions.create();
|
||||
// const ws = WaveSurfer.create({
|
||||
// container: waveformRef.current,
|
||||
// waveColor: '#ccb1ff',
|
||||
// progressColor: '#6e44ba',
|
||||
// // responsive: true,
|
||||
// height: 100,
|
||||
// hideScrollbar: true,
|
||||
// backend: 'WebAudio',
|
||||
// plugins: [regions],
|
||||
// });
|
||||
|
||||
// wavesurferRef.current = ws;
|
||||
// ws.load(`file://${filePath}`);
|
||||
|
||||
// ws.on('ready', () => {
|
||||
// setDuration(ws.getDuration());
|
||||
// regions.clearRegions();
|
||||
// // ws.clearRegions();
|
||||
// regions.addRegion({
|
||||
// start: trimStart,
|
||||
// end: trimEnd || ws.getDuration(),
|
||||
// color: 'rgba(132, 81, 224, 0.3)',
|
||||
// drag: false,
|
||||
// resize: true,
|
||||
// });
|
||||
// });
|
||||
|
||||
// regions.on('region-updated', (updatedRegion: any) => {
|
||||
// setRegion({
|
||||
// start: Math.max(0, updatedRegion.start),
|
||||
// end: Math.min(ws.getDuration(), updatedRegion.end),
|
||||
// });
|
||||
// });
|
||||
|
||||
// // eslint-disable-next-line consistent-return
|
||||
// return () => {
|
||||
// ws.destroy();
|
||||
// };
|
||||
// }, [filePath, trimStart, trimEnd]);
|
||||
|
||||
// const formatTime = (seconds: number) => {
|
||||
// const minutes = Math.floor(seconds / 60);
|
||||
// const remainingSeconds = Math.floor(seconds % 60);
|
||||
// return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
|
||||
// };
|
||||
|
||||
// return (
|
||||
// <div className="audio-trimmer-item" data-filepath={filePath}>
|
||||
// <div className="audio-trimmer-header">
|
||||
// <div className="audio-trimmer-title-container">
|
||||
// <div className="audio-trimmer-title">
|
||||
// {title || getBaseName(filePath)}
|
||||
// </div>
|
||||
// <div className="audio-trimmer-filename">
|
||||
// {title ? getBaseName(filePath) : 'hidden'}
|
||||
// </div>
|
||||
// <div className="audio-trimmer-section">{section}</div>
|
||||
// </div>
|
||||
// <div className="audio-trimmer-controls">
|
||||
// <button
|
||||
// type="button"
|
||||
// className="play-pause-btn"
|
||||
// onClick={() => {
|
||||
// const ws = wavesurferRef.current;
|
||||
// if (!ws) return;
|
||||
// if (ws.isPlaying()) {
|
||||
// ws.pause();
|
||||
// } else {
|
||||
// ws.play(region.start, region.end);
|
||||
// }
|
||||
// }}
|
||||
// >
|
||||
// ▶️
|
||||
// </button>
|
||||
// <button
|
||||
// type="button"
|
||||
// className="save-trim"
|
||||
// onClick={() => onSave?.(region.start, region.end, title)}
|
||||
// >
|
||||
// 💾
|
||||
// </button>
|
||||
// <button type="button" className="delete-btn" onClick={onDelete}>
|
||||
// 🗑️
|
||||
// </button>
|
||||
// </div>
|
||||
// </div>
|
||||
// <div className="waveform-container">
|
||||
// <div ref={waveformRef} className="waveform" />
|
||||
// </div>
|
||||
// <div className="trim-info">
|
||||
// <div className="trim-time">
|
||||
// <span>Start: </span>
|
||||
// <span className="trim-start-time">{formatTime(region.start)}</span>
|
||||
// </div>
|
||||
// <div className="trim-time">
|
||||
// <span>End: </span>
|
||||
// <span className="trim-end-time">{formatTime(region.end)}</span>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
|
||||
// export default AudioTrimmer;
|
||||
Reference in New Issue
Block a user