这是我参与「第五届青训营 」伴学笔记创作活动的第10天。
今日主要是学习使用抖声项目中视频Feed流。
一、直接运行项目
双击抖声中“我”,输入本地IP地址。go build打包项目案例,并运行生成的exe文件。
feed接口接收到的视频是从DemoVideos读取视频列表。这里从demo_data可以发现,读取的视频地址是PlayUrl,封面是CoverUrl。
二、读取位置改为本地
这里我们把public目录下的新建cover文件夹存放封面图片,新建play文件夹存放视频。这里我又放入了一个视频,来验证客户端能否读取服务端信息。
修改DemoVideos信息,这里要修改PlayUrl和CoverUrl地址信息。其中xxx.xxx.xxx.xxx:8080”要把服务端IP地址输入,/static/会访问服务端public文件夹目录下的内容,由于我新建了play存放视频,cover存放封面,这里static后面跟随的是public目录下的视频和封面地址。这里我存放了两个视频。
回到app,我们可以播放服务端的第二个视频。我们可以看到服务端接收到的get请求。
三、结合gorm
这里我把demo_data的信息全部放入数据库中,通过访问数据库来获取视频地址等信息。以下是修改以后的demo_data.go内容。其中dsn根据数据库信息自行修改,dbCreate我放在第四部分介绍。
package controller
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var DemoVideos = []Video{}
var DemoComments = []Comment{}
var DemoUsers = []User{}
func (v Video) TableName() string {
return "videos"
}
func (u User) TableName() string {
return "users"
}
func InitVideo() error {
dsn := "username:password@tcp(192.168.0.103:3306)/douyin?charset=utf8&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
fmt.Println(err)
fmt.Println("failed to connect database")
return err
}
db.Find(&DemoUsers)
var demoVideoL = Video{}
db.Last(&demoVideoL)
for i := 1; i <= int(demoVideoL.Id); i++ {
var demoVideo = Video{}
db.Preload("Author").Find(&demoVideo, i)
demoVideo.PlayUrl = "http://192.168.0.103:8080/static/play/" + demoVideo.PlayUrl
demoVideo.CoverUrl = "http://192.168.0.103:8080/static/cover/" + demoVideo.CoverUrl
DemoVideos = append(DemoVideos, demoVideo)
}
var DemoCommentL = Comment{}
db.Last(&DemoCommentL)
for i := 1; i <= int(DemoCommentL.Id); i++ {
var demoComment = Comment{}
db.Preload("User").Find(&demoComment, i)
DemoComments = append(DemoComments, demoComment)
}
return nil
}
func dbCreate(v Video) error {
dsn := "username:password@tcp(192.168.0.103:3306)/douyin?charset=utf8&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
fmt.Println(err)
fmt.Println("failed to connect database")
return err
}
db.Model(&Video{}).Omit("Author").Create(&v)
DemoVideos = append(DemoVideos, v)
return nil
}
由于数据存放的是视频名称和封面名称,这里要遍历DemoVideos把视频和封面地址补充完整。db.Preload是预加载功能,如果我在数据库中添加外键的话可以通过预加载直接将结构体中的内联关系进行匹配。
这里我觉的这个方法并不好,如果视频数据量一旦大就会运行效率非常低下。
下面是我修改的common.go文件,其中AuthorId是新增的,是记录外键标注的作者Id。由于数据库中我用这个字段名作为外键去连接users表,gorm”foreignKey:AuthorId”是能够预加载通过外键去匹配User信息。
package controller
type Response struct {
StatusCode int32 `json:"status_code"`
StatusMsg string `json:"status_msg,omitempty"`
}
type Video struct {
Id int64 `json:"id,omitempty"`
AuthorId int64 `json:"author_id,omitempty"`
Author User `json:"author,omitempty" gorm:"foreignKey:AuthorId"`
PlayUrl string `json:"play_url,omitempty"`
CoverUrl string `json:"cover_url,omitempty"`
FavoriteCount int64 `json:"favorite_count,omitempty"`
CommentCount int64 `json:"comment_count,omitempty"`
IsFavorite bool `json:"is_favorite,omitempty"`
}
type Comment struct {
Id int64 `json:"id,omitempty"`
User User `json:"user" gorm:"foreignKey:Id"`
Content string `json:"content,omitempty"`
CreateDate string `json:"create_date,omitempty"`
}
type User struct {
Id int64 `json:"id,omitempty"`
Name string `json:"name,omitempty"`
FollowCount int64 `json:"follow_count,omitempty"`
FollowerCount int64 `json:"follower_count,omitempty"`
IsFollow bool `json:"is_follow,omitempty"`
}
type Message struct {
Id int64 `json:"id,omitempty"`
Content string `json:"content,omitempty"`
CreateTime string `json:"create_time,omitempty"`
}
type MessageSendEvent struct {
UserId int64 `json:"user_id,omitempty"`
ToUserId int64 `json:"to_user_id,omitempty"`
MsgContent string `json:"msg_content,omitempty"`
}
type MessagePushEvent struct {
FromUserId int64 `json:"user_id,omitempty"`
MsgContent string `json:"msg_content,omitempty"`
}
四、发布视频
这里我在demo_data.go里面新增了dbCreate方法,public.go主要是修改了新增视频这部分,主要是saveFile这里把”./public”改为”./public/play”,然后再加上一个数据库新增视频信息。
filename := filepath.Base(data.Filename)
user := usersLoginInfo[token]
finalName := fmt.Sprintf("%d_%s", user.Id, filename)
saveFile := filepath.Join("./public/play", finalName)
if err := c.SaveUploadedFile(data, saveFile); err != nil {
c.JSON(http.StatusOK, Response{
StatusCode: 1,
StatusMsg: err.Error(),
})
return
}
var video = Video{Id: int64(len(DemoVideos)+1), AuthorId: user.Id, Author: user, PlayUrl: finalName,
CoverUrl: finalName, FavoriteCount: 0, CommentCount: 0,
IsFavorite: false}
dbCreate(video)
发布后public文件夹下面会新增视频,数据库也有新增记录。但是我并没有解决封面的问题,这里我只能手动在cover文件夹下新增封面信息才能播放视频,不然客户端播放视频会跳出无法播放的错误信息。这里应该再增加一个saveFile来保存封面,但是我没有找到获取封面图片的办法。
总结
今日学习主要是想结合前面提到的gorm和gin结合使用,由于个人能力有限,我使用的视频播放方法并不好。包括后面的发布视频并没有完全实现。今天的学习主要还是工具使用的练习。
参考
预加载 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.