From 675cf72271fc1035adb360738e39b913becf3905 Mon Sep 17 00:00:00 2001 From: Rogee Date: Wed, 4 Dec 2024 19:30:30 +0800 Subject: [PATCH] feat: add discover medias task --- backend/modules/tasks/discover_medias.go | 115 ++++++++++++++++-- backend/modules/tasks/discover_medias_test.go | 21 ---- backend/modules/tasks/provider.gen.go | 10 +- 3 files changed, 111 insertions(+), 35 deletions(-) diff --git a/backend/modules/tasks/discover_medias.go b/backend/modules/tasks/discover_medias.go index ea5781f..1bca994 100644 --- a/backend/modules/tasks/discover_medias.go +++ b/backend/modules/tasks/discover_medias.go @@ -1,6 +1,7 @@ package tasks import ( + "encoding/json" "os" "os/exec" "path/filepath" @@ -8,16 +9,14 @@ import ( "backend/modules/medias" - "github.com/etherlabsio/go-m3u8/m3u8" + "github.com/google/uuid" "github.com/pkg/errors" "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" - hashids "github.com/speps/go-hashids/v2" ) // @provider type DiscoverMedias struct { - hashId *hashids.HashID mediasSvc *medias.Service log *logrus.Entry `inject:"false"` @@ -28,8 +27,84 @@ func (d *DiscoverMedias) Prepare() error { return nil } -func (d *DiscoverMedias) getHashID(ids ...int64) (string, error) { - return d.hashId.EncodeInt64(ids) +func (d *DiscoverMedias) Run(from, to string) error { + 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) { @@ -129,12 +204,30 @@ func (d *DiscoverMedias) ffmpegVideoToM3U8(input string, output string) error { return nil } -// parseM3u8File parse the m3u8 file -func (d *DiscoverMedias) parseM3u8File(file string) (*m3u8.Playlist, error) { - platList, err := m3u8.ReadFile(file) - if err != nil { - return nil, errors.Wrapf(err, "read m3u8 file:%s", file) +func (d *DiscoverMedias) ffmpegAudioToM3U8(input string, output string) error { + output = filepath.Join(output, "audio") + if err := d.ensureDirectory(output); err != nil { + return errors.Wrapf(err, "ensure directory: %s", output) } - 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 } diff --git a/backend/modules/tasks/discover_medias_test.go b/backend/modules/tasks/discover_medias_test.go index eee982c..e094d70 100644 --- a/backend/modules/tasks/discover_medias_test.go +++ b/backend/modules/tasks/discover_medias_test.go @@ -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() { Convey("Test_getSubDirs", t.T(), func() { dirs, err := t.Svc.getSubDirs("/mnt/yangpingliang/动态曲谱") @@ -72,15 +63,3 @@ func (t *DiscoverMediasTestSuite) Test_ffmpegVideoToM3U8() { 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()) - }) -} diff --git a/backend/modules/tasks/provider.gen.go b/backend/modules/tasks/provider.gen.go index 26c903e..263b205 100755 --- a/backend/modules/tasks/provider.gen.go +++ b/backend/modules/tasks/provider.gen.go @@ -1,17 +1,21 @@ package tasks import ( + "backend/modules/medias" + "git.ipao.vip/rogeecn/atom/container" "git.ipao.vip/rogeecn/atom/utils/opt" - hashids "github.com/speps/go-hashids/v2" ) func Provide(opts ...opt.Option) error { if err := container.Container.Provide(func( - hashId *hashids.HashID, + mediasSvc *medias.Service, ) (*DiscoverMedias, error) { obj := &DiscoverMedias{ - hashId: hashId, + mediasSvc: mediasSvc, + } + if err := obj.Prepare(); err != nil { + return nil, err } return obj, nil }); err != nil {