generated from dellevin/template
22
This commit is contained in:
@@ -156,6 +156,93 @@ def analyze():
|
||||
})
|
||||
|
||||
|
||||
@bp.route('/manual-slice', methods=['POST'])
|
||||
def manual_slice():
|
||||
data = request.get_json()
|
||||
task_id = data.get('task_id')
|
||||
task = _tasks.get(task_id)
|
||||
if not task:
|
||||
return jsonify({'success': False, 'error': '任务不存在'}), 404
|
||||
|
||||
cut_points = sorted(data.get('cut_points', []))
|
||||
sr = task['sr']
|
||||
total = task['total']
|
||||
duration = task['duration']
|
||||
|
||||
valid = [p for p in cut_points if 0 < p < duration]
|
||||
if not valid:
|
||||
return jsonify({'success': False, 'error': '没有有效的切割点'}), 400
|
||||
|
||||
samples = [int(round(p * sr)) for p in valid]
|
||||
boundaries = [0] + samples + [total]
|
||||
ranges = [(boundaries[i], boundaries[i + 1])
|
||||
for i in range(len(boundaries) - 1)
|
||||
if boundaries[i + 1] > boundaries[i]]
|
||||
|
||||
task['ranges'] = ranges
|
||||
task['status'] = 'analyzed'
|
||||
|
||||
preview = [{'index': i, 'duration': round((e - b) / sr, 2), 'samples': e - b}
|
||||
for i, (b, e) in enumerate(ranges)]
|
||||
return jsonify({'success': True, 'count': len(ranges), 'preview': preview,
|
||||
'sample_rate': int(sr), 'channels': int(task['ch'])})
|
||||
|
||||
|
||||
@bp.route('/preview-range/<task_id>')
|
||||
def preview_range(task_id):
|
||||
task = _tasks.get(task_id)
|
||||
if not task:
|
||||
return jsonify({'error': '任务不存在'}), 404
|
||||
try:
|
||||
start = float(request.args.get('start', 0))
|
||||
end = float(request.args.get('end', task['duration']))
|
||||
except (ValueError, TypeError):
|
||||
return jsonify({'error': '参数错误'}), 400
|
||||
|
||||
sr = task['sr']
|
||||
ch = task['ch']
|
||||
begin = max(0, int(start * sr))
|
||||
end_sample = min(task['total'], int(end * sr))
|
||||
if end_sample <= begin:
|
||||
return jsonify({'error': '无效范围'}), 400
|
||||
|
||||
buf = io.BytesIO()
|
||||
with soundfile.SoundFile(task['src']) as src:
|
||||
src.seek(begin)
|
||||
frames = end_sample - begin
|
||||
data = src.read(frames)
|
||||
with soundfile.SoundFile(buf, mode='w', samplerate=sr, channels=ch,
|
||||
format='WAV') as dst:
|
||||
dst.write(data)
|
||||
buf.seek(0)
|
||||
return send_file(buf, mimetype='audio/wav')
|
||||
|
||||
|
||||
@bp.route('/waveform-peaks/<task_id>')
|
||||
def waveform_peaks(task_id):
|
||||
"""返回波形峰值数据,供前端绘制波形图"""
|
||||
task = _tasks.get(task_id)
|
||||
if not task:
|
||||
return jsonify({'error': '任务不存在'}), 404
|
||||
num_samples = int(request.args.get('samples', 400))
|
||||
with soundfile.SoundFile(task['src']) as f:
|
||||
sr = f.samplerate
|
||||
ch = f.channels
|
||||
total = len(f)
|
||||
samples_per_bucket = max(1, total // num_samples)
|
||||
peaks = []
|
||||
for i in range(num_samples):
|
||||
start = i * samples_per_bucket
|
||||
length = min(samples_per_bucket, total - start)
|
||||
if length <= 0:
|
||||
break
|
||||
data = f.read(length)
|
||||
if ch > 1:
|
||||
data = data.mean(axis=1)
|
||||
peaks.append(float(abs(data).max()))
|
||||
return jsonify({'peaks': peaks, 'duration': task['duration'], 'sr': sr})
|
||||
|
||||
|
||||
@bp.route('/slice', methods=['POST'])
|
||||
def start_slice():
|
||||
data = request.get_json()
|
||||
@@ -166,6 +253,16 @@ def start_slice():
|
||||
if not task.get('ranges'):
|
||||
return jsonify({'success': False, 'error': '请先分析'}), 400
|
||||
|
||||
# 支持选择性切割
|
||||
selected = data.get('selected_indices')
|
||||
all_ranges = task['ranges']
|
||||
if selected is not None and isinstance(selected, list) and len(selected) > 0:
|
||||
ranges = [all_ranges[i] for i in selected if 0 <= i < len(all_ranges)]
|
||||
else:
|
||||
ranges = all_ranges
|
||||
if not ranges:
|
||||
return jsonify({'success': False, 'error': '未选择任何片段'}), 400
|
||||
|
||||
task['status'] = 'slicing'
|
||||
task['progress'] = 0
|
||||
task['slices'] = []
|
||||
@@ -176,7 +273,6 @@ def start_slice():
|
||||
|
||||
def _do_slice():
|
||||
base = os.path.splitext(task['orig_name'])[0]
|
||||
ranges = task['ranges']
|
||||
total = len(ranges)
|
||||
for i, (begin, end) in enumerate(ranges):
|
||||
out_path = os.path.join(out_dir, f'{base}_{i:03d}.wav')
|
||||
|
||||
Reference in New Issue
Block a user