feat: add discover medias task
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package tasks
|
package tasks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -8,16 +9,14 @@ import (
|
|||||||
|
|
||||||
"backend/modules/medias"
|
"backend/modules/medias"
|
||||||
|
|
||||||
"github.com/etherlabsio/go-m3u8/m3u8"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
hashids "github.com/speps/go-hashids/v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// @provider
|
// @provider
|
||||||
type DiscoverMedias struct {
|
type DiscoverMedias struct {
|
||||||
hashId *hashids.HashID
|
|
||||||
mediasSvc *medias.Service
|
mediasSvc *medias.Service
|
||||||
|
|
||||||
log *logrus.Entry `inject:"false"`
|
log *logrus.Entry `inject:"false"`
|
||||||
@@ -28,8 +27,84 @@ func (d *DiscoverMedias) Prepare() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DiscoverMedias) getHashID(ids ...int64) (string, error) {
|
func (d *DiscoverMedias) Run(from, to string) error {
|
||||||
return d.hashId.EncodeInt64(ids)
|
d.log.Infof("Discover medias from: %s to: %s", from, to)
|
||||||
|
|
||||||
|
mapFile := filepath.Join(to, "map.json")
|
||||||
|
d.log.Infof("read in from: %s", mapFile)
|
||||||
|
|
||||||
|
b, err := os.ReadFile(mapFile)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "read file: %s", mapFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
type mediaUuidMap struct {
|
||||||
|
UUID string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
var store []mediaUuidMap
|
||||||
|
err = json.Unmarshal(b, &store)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "unmarshal json: %s", mapFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
storeMap := make(map[string]string)
|
||||||
|
for _, item := range store {
|
||||||
|
storeMap[item.Name] = item.UUID
|
||||||
|
}
|
||||||
|
|
||||||
|
dirs, err := d.getSubDirs(from)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "get sub dirs: %s", from)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dir := range dirs {
|
||||||
|
d.log.Infof("Discover medias in: %s", dir)
|
||||||
|
|
||||||
|
if _, ok := storeMap[dir]; ok {
|
||||||
|
d.log.Infof("Skip dir: %s", dir)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
dirPath := filepath.Join(from, dir)
|
||||||
|
|
||||||
|
uuid := uuid.New().String()
|
||||||
|
to := filepath.Join(to, uuid)
|
||||||
|
|
||||||
|
videos := d.globVideo(dirPath)
|
||||||
|
if len(videos) > 0 {
|
||||||
|
video := videos[0]
|
||||||
|
if err := d.ffmpegVideoToM3U8(video, to); err != nil {
|
||||||
|
return errors.Wrapf(err, "ffmpeg video to m3u8: %s", video)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
audios := d.globAudio(dirPath)
|
||||||
|
if len(audios) > 0 {
|
||||||
|
audio := audios[0]
|
||||||
|
if err := d.ffmpegAudioToM3U8(audio, to); err != nil {
|
||||||
|
return errors.Wrapf(err, "ffmpeg audio to m3u8: %s", audio)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
store = append(store, mediaUuidMap{
|
||||||
|
UUID: uuid,
|
||||||
|
Name: dir,
|
||||||
|
})
|
||||||
|
|
||||||
|
b, err := json.Marshal(store)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "marshal json: %s", mapFile)
|
||||||
|
}
|
||||||
|
if err := os.WriteFile(mapFile, b, os.ModePerm); err != nil {
|
||||||
|
return errors.Wrapf(err, "write file: %s", mapFile)
|
||||||
|
}
|
||||||
|
storeMap[dir] = uuid
|
||||||
|
d.log.Infof("Store map: %s", storeMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DiscoverMedias) getSubDirs(root string) ([]string, error) {
|
func (d *DiscoverMedias) getSubDirs(root string) ([]string, error) {
|
||||||
@@ -129,12 +204,30 @@ func (d *DiscoverMedias) ffmpegVideoToM3U8(input string, output string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseM3u8File parse the m3u8 file
|
func (d *DiscoverMedias) ffmpegAudioToM3U8(input string, output string) error {
|
||||||
func (d *DiscoverMedias) parseM3u8File(file string) (*m3u8.Playlist, error) {
|
output = filepath.Join(output, "audio")
|
||||||
platList, err := m3u8.ReadFile(file)
|
if err := d.ensureDirectory(output); err != nil {
|
||||||
if err != nil {
|
return errors.Wrapf(err, "ensure directory: %s", output)
|
||||||
return nil, errors.Wrapf(err, "read m3u8 file:%s", file)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return platList, nil
|
args := []string{
|
||||||
|
"-i", input,
|
||||||
|
"-c:a", "aac",
|
||||||
|
"-strict",
|
||||||
|
"-2",
|
||||||
|
"-f", "hls",
|
||||||
|
"-hls_time", "10",
|
||||||
|
"-hls_list_size", "0",
|
||||||
|
"-hls_segment_filename", filepath.Join(output, "%d.ts"),
|
||||||
|
filepath.Join(output, "index.m3u8"),
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("cmd: ffmpeg %s", strings.Join(args, " "))
|
||||||
|
logs, err := exec.Command("ffmpeg", args...).Output()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "ffmpeg audio to m3u8: %s", input)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.log.Infof("ffmpeg audio to m3u8: %s", logs)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,15 +31,6 @@ func Test_DiscoverMedias(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *DiscoverMediasTestSuite) Test_getHashID() {
|
|
||||||
Convey("TestDiscoverMedias_getHashID", t.T(), func() {
|
|
||||||
hashId, err := t.Svc.getHashID(10, 11, 12)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
t.T().Logf("HashID: %s", hashId)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *DiscoverMediasTestSuite) Test_getSubDirs() {
|
func (t *DiscoverMediasTestSuite) Test_getSubDirs() {
|
||||||
Convey("Test_getSubDirs", t.T(), func() {
|
Convey("Test_getSubDirs", t.T(), func() {
|
||||||
dirs, err := t.Svc.getSubDirs("/mnt/yangpingliang/动态曲谱")
|
dirs, err := t.Svc.getSubDirs("/mnt/yangpingliang/动态曲谱")
|
||||||
@@ -72,15 +63,3 @@ func (t *DiscoverMediasTestSuite) Test_ffmpegVideoToM3U8() {
|
|||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *DiscoverMediasTestSuite) Test_parseM3u8File() {
|
|
||||||
Convey("TestDiscoverMedias_parseM3u8File", t.T(), func() {
|
|
||||||
file := "/projects/mp-qvyun/backend/fixtures/medias/abc/video/index.m3u8"
|
|
||||||
playlist, err := t.Svc.parseM3u8File(file)
|
|
||||||
So(err, ShouldBeNil)
|
|
||||||
|
|
||||||
t.T().Logf("Live: %+v", playlist.IsLive())
|
|
||||||
t.T().Logf("IsMaster: %+v", playlist.IsMaster())
|
|
||||||
t.T().Logf("Size: %+v", playlist.Segments())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,17 +1,21 @@
|
|||||||
package tasks
|
package tasks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"backend/modules/medias"
|
||||||
|
|
||||||
"git.ipao.vip/rogeecn/atom/container"
|
"git.ipao.vip/rogeecn/atom/container"
|
||||||
"git.ipao.vip/rogeecn/atom/utils/opt"
|
"git.ipao.vip/rogeecn/atom/utils/opt"
|
||||||
hashids "github.com/speps/go-hashids/v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Provide(opts ...opt.Option) error {
|
func Provide(opts ...opt.Option) error {
|
||||||
if err := container.Container.Provide(func(
|
if err := container.Container.Provide(func(
|
||||||
hashId *hashids.HashID,
|
mediasSvc *medias.Service,
|
||||||
) (*DiscoverMedias, error) {
|
) (*DiscoverMedias, error) {
|
||||||
obj := &DiscoverMedias{
|
obj := &DiscoverMedias{
|
||||||
hashId: hashId,
|
mediasSvc: mediasSvc,
|
||||||
|
}
|
||||||
|
if err := obj.Prepare(); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
return obj, nil
|
return obj, nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user