没想到时隔一年多又掉进了bgm的大坑
这次的需求是用户先选择音乐,然后调起微信的录像api(此处有特殊样式,所以不能直接用选择视频文件录像那个方法),之后将用户拍摄的视频、选择的bgm传给后端,他那边加上水印合成视频返回给前端进行后面的操作。
但是
问题就出在但是
录制视频的时候也要求加上bgm,不然太突兀了,所以就相当于前端这边合成视频和音频,后端再合成水印。
一开始我想的是加个放在页面,录制的时候播放一下,拍好了再播放,假装合成了,其实还是后端去合成。但是用
播放音频的话,会影响视频麦克风的收声,录出来的视频只有一两秒有声音
还好及时求助公司大佬,他提出了可以调用全局背景音乐的方法来录制视频
下面展示代码
<page>
<view class="home">
<!-- 结果 -->
<view class="result" wx:if="{{videoSrc}}">
<video class="video " src="{{videoSrc}}" show-progress="{{false}}" muted='{{false}}' controls="{{true}}"></video>
<view class="btns">
<view class="btn" bindtap="initShoot">
<img clas='my_img' src='shoot/back.png' />
</view>
<view class="btn" bindtap='uploadViedo'>
<img clas='my_img' src='shoot/next.png' />
</view>
</view>
</view>
<!-- 录制 -->
<view class="duringShoot" wx:else>
<camera class="mycamera" mode="normal" device-position="front"></camera>
<view class="tips" wx:if="{{showWord}}">
<view class="word">
<view class="marquee_text" style="left:{{marqueeDistance2}}px">
<text>{{text}}</text>
<text wx:if="{{marquee2copy_status}}" style="margin-left:{{marquee2_margin}}px;">
{{text}}
</text>
</view>
</view>
<view class="icon" bindtap='getsentence'>
<img clas='my_img' src='shoot/refresh.png' />
</view>
</view>
<view class="rule" wx:else bindtap="showTips">
<img clas='my_img' src='shoot/tips.png' />
</view>
<view class="countdown" wx:if="{{duringVideo}}">倒计时:{{countdown}}s</view>
<view class="btns">
<view class="btn" bindtap="startRecord">
<img clas='my_img' src='shoot/btn.png' />
</view>
<view class="stop" bindtap="stopRecord" wx:if="{{duringVideo}}">
<img clas='my_img' src='shoot/stop.png' />
</view>
</view>
</view>
</view>
</page>
Page({
data: {
//录制
duringVideo: false,//在录制期间
countdown: 20,//倒计时
// 音乐
audioList: [],//音乐列表
audioUrl: '',//选中的音乐链接
},
onLoad(options) {
this.getBgms()
this.ctx = wx.createCameraContext()
this.setData({
audioUrl: this.data.audioList[options.index].url,
soundEnum: this.data.audioList[options.index].enumName
})
this.innerAudioContext = wx.createInnerAudioContext({
useWebAudioImplement: false // 是否使用 WebAudio 作为底层音频驱动,默认关闭。对于短音频、播放频繁的音频建议开启此选项,开启后将获得更优的性能表现。由于开启此选项后也会带来一定的内存增长,因此对于长音频建议关闭此选项
})
this.innerAudioContext.src = this.data.audioList[options.index].url
this.innerAudioContext.loop = true;
},
onUnload() {
clearInterval(this.timer)
//
},
//获取视频bgm
getBgms() {
this.API.Getbgm().then(res => {
console.log('Getbgmres', res);
if (res.code == 200) {
let audioList = res.data
this.setData({ audioList })
}
})
},
// --------------录像相关
// 重新录制
initShoot() {
clearInterval(this.timer)
this.setData({
showWord: false,
num: 1,
src: '',
videoSrc: '',
countdown: 20
})
},
startRecord() {
if (this.data.duringVideo == false) {
console.log('开始录像');
this.ctx.startRecord({
// timeout: 20,
success: (res) => {
console.log('startRecord')
clearInterval(this.timer)
this.setData({ duringVideo: true, src: '', videoSrc: '', countdown: 20 })
this.countdownTime()
this.innerAudioContext.play() // 播放
}
})
}
},
stopRecord() {
console.log('结束录像');
if (this.data.duringVideo == true) {
wx.showLoading({
title: '处理中...',
mask: true
});
clearInterval(this.timer)
this.setData({ duringVideo: false })
this.ctx.stopRecord({
compressed: true,
success: (res) => {
console.log('结束录像res', res);
wx.hideLoading();
this.setData({
src: res.tempThumbPath,
videoSrc: res.tempVideoPath
})
this.innerAudioContext.stop() // 播放
}, fail: (e) => {
console.log('fail', e);
this.toast('视频录制失败,请重新拍摄~')
this.initShoot()
}
})
}
},
// 倒计时
countdownTime() {
let time = 20
this.timer = setInterval(() => {
if (time > 0) {
time--;
console.log(time);
this.setData({ countdown: time })
} else {
clearInterval(this.timer)
this.stopRecord()
}
}, 1000);
},
// 上传视频
uploadViedo() {
wx.showLoading({
title: '合成中...',
mask: true
});
let file = this.data.videoSrc
let soundEnum = this.data.soundEnum
console.log('audioUrl', soundEnum, file);
//上传单个视频
this.API.CompoundVideo(soundEnum, file).then(res => {
console.log('----------res上传视频', res)
if (res.statusCode == 200) {
let jsondata = JSON.parse(res.data)
let videoPath = jsondata.data.videoUrl
let qrCodeUrl = jsondata.data.qrCodeUrl
console.log('res.data', res.data);
wx.navigateTo({
url: '/pages/result/result?videoPath=' + videoPath + '&qrCodeUrl=' + qrCodeUrl,
});
wx.hideLoading();
}
})
},
goNext() {
wx.navigateTo({
url: '/pages/result/result?videoPath=' + this.data.videoPath + '&qrCodeUrl=' + this.data.qrCodeUrl,
});
},
})
核心代码其实是
this.innerAudioContext = wx.createInnerAudioContext({
useWebAudioImplement: false // 是否使用 WebAudio 作为底层音频驱动,默认关闭。对于短音频、播放频繁的音频建议开启此选项,开启后将获得更优的性能表现。由于开启此选项后也会带来一定的内存增长,因此对于长音频建议关闭此选项
})
this.innerAudioContext.src = this.data.audioList[options.index].url
this.innerAudioContext.loop = true;
还有就是录制开始的时候调一下this.innerAudioContext.play()
,录制结束的时候调一下this.innerAudioContext.stop()
对了 在页面销毁的时候得把背景音乐关掉,不然左滑返回上一页啥的还是会有背景音乐
onUnload() {
clearInterval(this.timer)
clearInterval(this.interval)
this.innerAudioContext.stop() // 停止
//
},