如何将视频URL转MP3并保存至Firebase Storage?
问题:Node.js+Express服务提取视频音频保存至Firebase Storage后仍为原视频格式
使用Node.js搭配Express v4.18.2开发部署在Firebase的服务,需求是接收视频URL,提取音频转成MP3后保存到Firebase Storage。本地测试时能正常生成MP3文件,但生产环境无法用fs本地存储文件,且保存到Storage的文件虽后缀设为.mp3、contentType配置为audio/mpeg,实际仍是原视频格式,浏览器打开会播放视频。
已实现功能
- 通过Axios成功下载视频流
- 可正常将文件保存至Firebase Storage(无初始化或存储桶引用问题)
- 本地测试时能生成名为
output.mp3的正确音频文件 - 可获取
extractAudioFromVideo函数返回的Buffer数据
存在问题
- 生产环境无法使用fs本地保存文件
- 上传至Firebase Storage的文件仅修改了后缀和元数据,实际内容仍包含视频流,并非纯MP3音频
核心代码
下载视频函数
async function downloadVideo(videoUrl) { try { const response = await axios.get(videoUrl, { responseType: 'stream', }); if (response.status === 200) { return response.data; } else { throw new Error('Failed to fetch the video'); } } catch (error) { throw new Error('Error fetching the video: ' + error.message); } }
提取音频函数
async function extractAudioFromVideo(videoUrl) { try { const videoStream = await downloadVideo(videoUrl); // Create a PassThrough stream to pipe the video data const passThrough = new PassThrough(); videoStream.pipe(passThrough); const outputFile = 'output.mp3'; const outputStream = fs.createWriteStream(outputFile); return new Promise((resolve, reject) => { const audioBuffers = []; passThrough.on('data', chunk => { audioBuffers.push(chunk) outputStream.write(chunk); // Write chunks to a local file }); passThrough.on('error', err => { reject(err); }); ffmpeg() .input(passThrough) .output('/dev/null') // Null output as a placeholder .outputOptions('-vn') // Extract audio only .noVideo() .audioQuality(0) .audioCodec('libmp3lame') // Set audio codec .format('mp3') .on('end', () => { const audioBuffer = Buffer.concat(audioBuffers) if (audioBuffer.length > 0) { resolve(audioBuffer); } else { reject(new Error('Empty audio buffer')); } }) .on('error', err => reject(err)) .run(); }) } catch (error) { throw new Error('Error extracting audio: ' + error.message); } }
保存至Firebase Storage函数
async function saveAudioToFirebase(audioBuffer, fileName) { try { let storage = admin.storage() let storageRef = storage.bucket(serviceAccount.storage_bucket_content) const file = storageRef.file(fileName) // Specify the desired file name here const renamedFileName = fileName.replace(/\.[^/.]+$/, '.mp3'); // Change the file extension to .mp3 await file.save(audioBuffer, { metadata: { contentType: 'audio/mpeg', // Adjust the content type as needed }, }); await file.setMetadata({ contentType: 'audio/mpeg' }) await file.move(renamedFileName); // Rename the file with the .mp3 extension console.log('Audio saved to Firebase Storage.'); } catch (error) { console.error('Error saving audio to Firebase Storage:', error); } }
愿意尝试tmp等第三方库,只要能解决问题。
内容的提问来源于stack exchange,提问作者Hello World
相关产品推荐
相关产品推荐

