这是我参与「第三届青训营 -后端场」笔记创作活动的的第4篇笔记。
1、关于mysql无法处理time类型的解决方式:
设置数据库参数
DataSource: root:1026@tcp(localhost:3306)/douyin?charset=utf8mb4&parseTime=True&loc=Local
2、go-zero自带的handler解析方法无法获取MultipartForm参数,手动获取报文参数:
r.ParseMultipartForm(128)
paraMap := r.MultipartForm
req.Token = paraMap.Value["token"][0]
req.Title = paraMap.Value["title"][0]
ptr := paraMap.File["data"][0]
//视频流文件
file, err := ptr.Open()
data, err := ioutil.ReadAll(file)
3、为了保证视频图片的唯一性,我们采用video_id+时间戳的命名方式存放在数据库中:
name := strconv.Itoa(int(user_id)) + strconv.Itoa(int(time.Now().Unix()))
//保存视频文件到本地
err = ioutil.WriteFile(types.SavePlayURL+name+".mp4", req.Data, 0644)
4、关于视频封面,我们采用ffmpeg音视频工具对视频流帧进行封面的抓取,这里简单的模拟cmd抓取视频的第一帧生成图片并保存到本地:
cmd := exec.Command("ffmpeg", "-i", types.SavePlayURL+name+".mp4", "-vframes", "1", "-f", "image2", types.SaveCoverURL+name+".png")
fmt.Println(cmd)
if err := cmd.Start(); err != nil { // 运行命令
log.Fatal(err)
}
5、数据库中存放获取视频及图片的路由地址:
publishVideo := model.Video{
CreateTime: time.Now(),
UserId: user_id,
PlayUrl: types.PlayURL + name + ".mp4",
CoverUrl: types.CoverURL + name + ".png",
FavoriteCount: 0,
CommentCount: 0,
Title: req.Title,
}
6、安卓模拟器的抖声app访问本地端口时,不能使用本地的ip地址:
模拟器访问本地端口时,会受到防火墙的阻拦,需要采用10.0.2.2的地址进行访问。
7、api到本地路径的路由转换:
server.AddRoutes(
[]rest.Route{
{
Method: http.MethodGet,
Path: "/static/play/:id",
Handler: func(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
type my_req struct {
id string `path:"id"`
}
//var req my_req
strs := strings.Split(r.URL.Path, "/")
fmt.Println(strs[len(strs)-1])
/**if err := httpx.ParsePath(r, &req); err != nil {
fmt.Println(err)
httpx.Error(w, err)
return
}**/
http.ServeFile(w, r, types.SavePlayURL + strs[len(strs)-1])
}
}(serverCtx),
},
)
7、最后将返回feed流中最后一条视频的创建时间,作为下一次latest_time时间戳对返回feed流进行限制;若已经没有视频了,则返回time.Now()作为时间戳,重头开始刷取视频:
if len(videos) == 0 {
nextTime = time.Now()
} else {
nextTime = videos[len(videos)-1].CreateTime
}