Flutter通过WebSocket传输媒体文件到小程序

前言

上一篇写了小程序通过WebSocket控制Flutter App进行拍照录像,那么问题又来了,小程序想要预览两部App拍摄的视频怎么办?

我想了三种方法,并实现了其中两种:

  1. 在flutter录像完毕后上传至cos,并且在上传成功的回调中通过socket将cos路径传输给小程序
  2. 在录像过程中传递数据流至小程序,类似“直播”的效果
  3. 在录像完毕后直接将视频源文件通过socket传输给小程序,小程序将视频保存成本地文件渲染出来

第一种方法在网速较慢的时候,从录像完毕到可以预览的周期有点长,并且如果拍摄并不满意,就得浪费一些cos内存,不划算。第二种方法小程序需要接收rtmp格式的数据流,在flutter中处理的比较复杂,并且小程序审核需要七天的时间(避免涉x嘛,你懂的)。于是我选择了第三种方法,传输速度较快,实现起来也较为方便。

思路

拍摄完毕拿到路径之后,通过 file.readAsBytes转化为字节流,然后直接通过socket.add()将其传输出去。小程序通过wx.getFileSystemManager().writeFile 将文件写下来,保存到本地

image

Flutter部分

这个方法接收媒体路径,接着通过 File file = new File(path) 得到这个文件,再通过 await file.readAsBytes() 将其转化为字节流 imageBytes,最后将其返回出去

1
2
3
4
5
6
//  转换字节流
static Future image2Base64(String path) async {
File file = new File(path);
List<int> imageBytes = await file.readAsBytes();
return imageBytes;
}

那么当停止录像的时候把路径作为参数传递给这个方法,他的回调就是 imageBytes,将其通过socket传递给小程序就好了

1
2
3
4
5
6
7
8
9
10
//  停止摄像
void onStopButtonPressed() {
stopVideoRecording().then((_) {

// 调用方法
image2Base64(videoPath).then((data){
socket.add(data);
});
});
}

小程序部分

监听传递过来的消息,然后通过 wx.getFileSystemManager().writeFile 方法写文件,本地路径自定义,最后将本地路径在 video 标签中渲染出来就好了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
socketTask2.onMessage((res) => {
const FILE_BASE_NAME = "tmp_base64src"; //自定义文件名
const timestamp = new Date().getTime();

const filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME}-${timestamp}.mp4`;

wx.getFileSystemManager().writeFile({
filePath,
data: res.data,
encoding: "binary",
success() {
console.log(filePath)
that.setState({
mediaPath: filePath
})
},
fail() {
return new Error("ERROR_BASE64SRC_WRITE");
}
});
})
1
<Video src={mediaPath} />

image