Fix WebDAV music seeking functionality
- Add proxy endpoint for WebDAV streaming with authentication - Implement range request support for audio seeking - Update streaming endpoint to use proxy for WebDAV, presigned URLs for S3 - Add proper HTTP headers for audio streaming (Accept-Ranges, Content-Range) - Fix music player seeking issue where clicking progress bar would reset playback The WebDAV integration now supports proper audio seeking by using a backend proxy that handles WebDAV authentication and range requests, allowing users to click anywhere on the progress bar to seek to that position in the track.
This commit is contained in:
parent
9de7564c18
commit
e58d42bea2
@ -371,20 +371,75 @@ router.get('/:id/stream', async (req, res) => {
|
||||
return res.status(404).json({ error: 'Music file not found' });
|
||||
}
|
||||
|
||||
// Use presigned URL for secure access instead of direct URL
|
||||
const presignedUrl = await storageService.getPresignedUrl(musicFile.s3Key, 3600); // 1 hour expiry
|
||||
|
||||
res.json({
|
||||
streamingUrl: presignedUrl,
|
||||
musicFile,
|
||||
contentType: musicFile.contentType || undefined,
|
||||
});
|
||||
// For WebDAV, use a proxy endpoint to handle authentication
|
||||
// For S3, use presigned URL for direct access
|
||||
const config = await StorageProviderFactory.loadConfig();
|
||||
if (config.provider === 'webdav') {
|
||||
// Use proxy endpoint for WebDAV to handle authentication
|
||||
const proxyUrl = `${req.protocol}://${req.get('host')}/api/music/${musicFile._id}/proxy`;
|
||||
res.json({
|
||||
streamingUrl: proxyUrl,
|
||||
musicFile,
|
||||
contentType: musicFile.contentType || undefined,
|
||||
});
|
||||
} else {
|
||||
// Use presigned URL for S3
|
||||
const presignedUrl = await storageService.getPresignedUrl(musicFile.s3Key, 3600); // 1 hour expiry
|
||||
res.json({
|
||||
streamingUrl: presignedUrl,
|
||||
musicFile,
|
||||
contentType: musicFile.contentType || undefined,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Streaming error:', error);
|
||||
res.status(500).json({ error: 'Failed to get streaming URL' });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Proxy endpoint for WebDAV streaming with authentication
|
||||
*/
|
||||
router.get('/:id/proxy', async (req, res) => {
|
||||
try {
|
||||
const musicFile = await MusicFile.findById(req.params.id);
|
||||
if (!musicFile) {
|
||||
return res.status(404).json({ error: 'Music file not found' });
|
||||
}
|
||||
|
||||
// Set appropriate headers for audio streaming
|
||||
res.setHeader('Content-Type', musicFile.contentType || 'audio/mpeg');
|
||||
res.setHeader('Accept-Ranges', 'bytes');
|
||||
res.setHeader('Cache-Control', 'public, max-age=3600');
|
||||
|
||||
// Get the file content from WebDAV
|
||||
const fileBuffer = await storageService.getFileContent(musicFile.s3Key);
|
||||
|
||||
// Handle range requests for seeking
|
||||
const range = req.headers.range;
|
||||
if (range) {
|
||||
const fileSize = fileBuffer.length;
|
||||
const parts = range.replace(/bytes=/, "").split("-");
|
||||
const start = parseInt(parts[0], 10);
|
||||
const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
|
||||
const chunksize = (end - start) + 1;
|
||||
const chunk = fileBuffer.slice(start, end + 1);
|
||||
|
||||
res.status(206);
|
||||
res.setHeader('Content-Range', `bytes ${start}-${end}/${fileSize}`);
|
||||
res.setHeader('Content-Length', chunksize.toString());
|
||||
res.end(chunk);
|
||||
} else {
|
||||
// No range request, send entire file
|
||||
res.setHeader('Content-Length', fileBuffer.length.toString());
|
||||
res.end(fileBuffer);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Proxy streaming error:', error);
|
||||
res.status(500).json({ error: 'Failed to stream music file' });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Get presigned URL for secure access
|
||||
*/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user