mirror of
https://github.com/ZHANGTIANYAO1/teamspeak-music-bot.git
synced 2026-10-02 04:52:50 +08:00
feat: implement seeking (FFmpeg -ss restart), fix lyrics sync with seekOffset
- AudioPlayer.seek() restarts FFmpeg with -ss parameter for actual seeking - New POST /api/player/:botId/seek endpoint - BotStatus includes seekOffset and playStartTime from server - Frontend elapsed = seekOffset + (now - playStartedAt) - Progress bar click now seeks to clicked position - All timing actions use _resetTiming() helper with seekOffset - Lyrics sync uses store.elapsed which includes seekOffset Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
080c2836c9
commit
1cdface33c
5 files changed
+101
-50
No files matched your search
@@ -74,6 +74,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, onMounted, onUnmounted } from 'vue';
|
||||
import { Icon } from '@iconify/vue';
|
||||
import axios from 'axios';
|
||||
import { usePlayerStore } from '../stores/player.js';
|
||||
import CoverArt from './CoverArt.vue';
|
||||
import Queue from './Queue.vue';
|
||||
@@ -101,10 +102,10 @@ function formatTime(seconds: number): string {
|
||||
}
|
||||
|
||||
function updateProgress() {
|
||||
// Directly compute elapsed from raw values (bypass Vue reactivity)
|
||||
const bot = store.activeBot;
|
||||
const seekOff = store.seekOffset;
|
||||
if (bot?.playing && !bot.paused && store.playStartedAt > 0) {
|
||||
currentElapsed.value = (Date.now() - store.playStartedAt) / 1000;
|
||||
currentElapsed.value = seekOff + (Date.now() - store.playStartedAt) / 1000;
|
||||
} else if (bot?.paused) {
|
||||
currentElapsed.value = store.pausedElapsed;
|
||||
}
|
||||
@@ -117,17 +118,22 @@ function updateProgress() {
|
||||
rafId = requestAnimationFrame(updateProgress);
|
||||
}
|
||||
|
||||
function onProgressClick(e: MouseEvent) {
|
||||
async function onProgressClick(e: MouseEvent) {
|
||||
const bar = progressBarRef.value;
|
||||
if (!bar) return;
|
||||
if (!bar || !store.activeBotId) return;
|
||||
const rect = bar.getBoundingClientRect();
|
||||
const ratio = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
|
||||
const duration = currentSong.value?.duration ?? 0;
|
||||
const seekTime = ratio * duration;
|
||||
// Can't seek server-side FFmpeg stream — show tooltip with target time
|
||||
progressTooltipTime.value = `跳转不可用 (${formatTime(seekTime)})`;
|
||||
progressTooltipVisible.value = true;
|
||||
setTimeout(() => { progressTooltipVisible.value = false; }, 1500);
|
||||
|
||||
try {
|
||||
await axios.post(`/api/player/${store.activeBotId}/seek`, { position: seekTime });
|
||||
store.seekOffset = seekTime;
|
||||
store.playStartedAt = Date.now();
|
||||
store.pausedElapsed = 0;
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
function onProgressHover(e: MouseEvent) {
|
||||
|
||||
Reference in new issue
Block a user