Compare commits

...

10 Commits

Author SHA1 Message Date
Rogee
b5961c12f7 feat: support playback speed
Some checks failed
Build TGExporter / Build (push) Failing after 38s
2025-01-07 22:49:19 +08:00
Rogee
2673c9fdde feat: add cron message notify 2025-01-06 19:24:11 +08:00
Rogee
019297d261 fix: ios player 2025-01-04 01:02:35 +08:00
Rogee
9df2663b6e feat: add charge codes 2024-12-28 16:38:46 +08:00
Rogee
cee14cb3fd fix: play segments 2024-12-28 16:05:25 +08:00
Rogee
dae2941168 fix: issues with default player 2024-12-28 15:17:19 +08:00
Rogee
464937cf84 fix: video radio 2024-12-28 12:22:56 +08:00
Rogee
549b18daf0 feat: add codes 2024-12-21 15:13:38 +08:00
Rogee
9ef5707ca2 feat: set worker duration to 1hour 2024-12-19 22:57:40 +08:00
Rogee
24553e9875 feat: update by query 2024-12-19 22:56:54 +08:00
26 changed files with 243 additions and 153 deletions

View File

@@ -12,6 +12,5 @@ func Provide(opts ...opt.Option) error {
}); err != nil {
return err
}
return nil
}

View File

@@ -153,7 +153,7 @@ func (d *DiscoverMedias) getFileMD5(filePath string) (string, error) {
}
// extractAudio extract audio from video
func (d *DiscoverMedias) extractAudio(video string, output string) error {
func (d *DiscoverMedias) extractAudio(video, output string) error {
args := []string{
"-i", video,
"-vn",
@@ -303,7 +303,7 @@ func (d *DiscoverMedias) runCleanup(to string) {
}
// getSnapshot get the snapshot of target seconds of a video
func (d *DiscoverMedias) ffmpegVideoToPoster(video string, output string) error {
func (d *DiscoverMedias) ffmpegVideoToPoster(video, output string) error {
args := []string{
"-y", // 添加 -y 参数强制覆盖
"-i", video,

View File

@@ -21,6 +21,5 @@ func Provide(opts ...opt.Option) error {
}); err != nil {
return err
}
return nil
}

View File

@@ -21,6 +21,5 @@ func Provide(opts ...opt.Option) error {
}); err != nil {
return err
}
return nil
}

View File

@@ -21,7 +21,6 @@ func Provide(opts ...opt.Option) error {
}); err != nil {
return err
}
if err := container.Container.Provide(func(
userSvc *users.Service,
) (*Create, error) {
@@ -35,7 +34,6 @@ func Provide(opts ...opt.Option) error {
}); err != nil {
return err
}
if err := container.Container.Provide(func(
userSvc *users.Service,
) (*Expire, error) {
@@ -49,6 +47,5 @@ func Provide(opts ...opt.Option) error {
}); err != nil {
return err
}
return nil
}

View File

@@ -8,7 +8,7 @@ import (
"github.com/gofiber/fiber/v3"
log "github.com/sirupsen/logrus"
hashids "github.com/speps/go-hashids/v2"
"github.com/speps/go-hashids/v2"
)
// @provider
@@ -82,7 +82,8 @@ func (c *Controller) MediaIndex(ctx fiber.Ctx) error {
if claim == nil {
return errorx.RequestUnAuthorized
}
// c.Locals(consts.CtxKeyJwt, token)
token := fiber.Locals[string](ctx, consts.CtxKeyJwt)
model, err := c.svc.GetMediaByHash(ctx.Context(), claim.TenantID, hash)
if err != nil {
log.WithField("action", "medias.MediaIndex").WithError(err).Error("GetMediaByHash")
@@ -95,12 +96,13 @@ func (c *Controller) MediaIndex(ctx fiber.Ctx) error {
return err
}
playlist, err := c.svc.GetM3U8(ctx.Context(), claim.TenantID, mediaType, model.Hash, bought)
playlist, err := c.svc.GetM3U8(ctx.Context(), claim.TenantID, mediaType, model.Hash, bought, token)
if err != nil {
log.WithField("action", "medias.MediaIndex").WithError(err).Error("GetMediaPlaylist")
return err
}
ctx.Set("Content-Type", "application/vnd.apple.mpegurl")
return ctx.SendString(playlist.String())
}
@@ -131,6 +133,7 @@ func (c *Controller) MediaSegment(ctx fiber.Ctx) error {
}
filepath := c.svc.GetSegmentPath(ctx.Context(), mediaType, model.TenantID, model.Hash, segments[0])
ctx.Set("Content-Type", "video/mp2t")
return ctx.SendFile(filepath)
}

View File

@@ -8,7 +8,7 @@ import (
"git.ipao.vip/rogeecn/atom/container"
"git.ipao.vip/rogeecn/atom/contracts"
"git.ipao.vip/rogeecn/atom/utils/opt"
hashids "github.com/speps/go-hashids/v2"
"github.com/speps/go-hashids/v2"
)
func Provide(opts ...opt.Option) error {
@@ -24,7 +24,6 @@ func Provide(opts ...opt.Option) error {
}); err != nil {
return err
}
if err := container.Container.Provide(func(
controller *Controller,
) (contracts.HttpRoute, error) {
@@ -38,7 +37,6 @@ func Provide(opts ...opt.Option) error {
}, atom.GroupRoutes); err != nil {
return err
}
if err := container.Container.Provide(func(
db *sql.DB,
hashIds *hashids.HashID,
@@ -56,6 +54,5 @@ func Provide(opts ...opt.Option) error {
}); err != nil {
return err
}
return nil
}

View File

@@ -18,6 +18,7 @@ import (
"backend/providers/storage"
. "github.com/go-jet/jet/v2/postgres"
"github.com/go-jet/jet/v2/qrm"
"github.com/grafov/m3u8"
"github.com/pkg/errors"
"github.com/samber/lo"
@@ -163,7 +164,7 @@ func (svc *Service) List(ctx context.Context, tenantId, userId int64, filter *Li
}
// GetUserBoughtMedias
func (svc *Service) GetUserBoughtMedias(ctx context.Context, tenant int64, userID int64) ([]int64, error) {
func (svc *Service) GetUserBoughtMedias(ctx context.Context, tenant, userID int64) ([]int64, error) {
log := svc.log.WithField("method", "GetUserBoughtMedias")
tbl := table.UserMedias
@@ -229,11 +230,21 @@ func (svc *Service) Upsert(ctx context.Context, tenantId int64, item media_store
}
tbl := table.Medias
stmt := tbl.
INSERT(tbl.TenantID, tbl.Hash, tbl.Title, tbl.Price, tbl.Duration, tbl.Resources, tbl.Publish).
VALUES(Int(tenantId), String(item.Hash), String(item.Name), Int(item.Price()), Int(item.Duration), Json(resources.MustValue()), Bool(true)).
ON_CONFLICT(tbl.Hash).
DO_UPDATE(
// if hash exists then update
stmt := tbl.SELECT(tbl.ID.AS("id")).WHERE(tbl.Hash.EQ(String(item.Hash)))
log.Debug(stmt.DebugSql())
var m struct {
ID int64
}
if err := stmt.QueryContext(ctx, svc.db, &m); err != nil && !errors.Is(err, qrm.ErrNoRows) {
return errors.Wrapf(err, "query media by hash %s", item.Hash)
}
if m.ID > 0 {
// update media
stmt2 := tbl.
UPDATE().
SET(
tbl.Title.SET(String(item.Name)),
tbl.Price.SET(Int(item.Price())),
@@ -241,19 +252,34 @@ func (svc *Service) Upsert(ctx context.Context, tenantId int64, item media_store
tbl.Duration.SET(Int(item.Duration)),
tbl.Publish.SET(Bool(true)),
tbl.UpdatedAt.SET(TimestampT(time.Now())),
),
)
log.Debug(stmt.DebugSql())
).
WHERE(tbl.ID.EQ(Int(m.ID)))
log.Debug(stmt2.DebugSql())
if _, err := stmt.ExecContext(ctx, svc.db); err != nil {
return errors.Wrapf(err, "upsert media: %s %s", item.Hash, item.Name)
if _, err := stmt2.ExecContext(ctx, svc.db); err != nil {
return errors.Wrapf(err, "update media: %s %s", item.Hash, item.Name)
}
svc.log.Infof("update media: %d %s %s", m.ID, item.Hash, item.Name)
return nil
}
stmt3 := tbl.
INSERT(tbl.TenantID, tbl.Hash, tbl.Title, tbl.Price, tbl.Duration, tbl.Resources, tbl.Publish).
VALUES(Int(tenantId), String(item.Hash), String(item.Name), Int(item.Price()), Int(item.Duration), Json(resources.MustValue()), Bool(true)).
ON_CONFLICT(tbl.Hash).
DO_NOTHING()
log.Debug(stmt3.DebugSql())
if _, err := stmt3.ExecContext(ctx, svc.db); err != nil {
return errors.Wrapf(err, "insert into media: %s %s", item.Hash, item.Name)
}
svc.log.Infof("insert media: %s %s", item.Hash, item.Name)
return nil
}
// get video m3u8
func (svc *Service) GetM3U8(ctx context.Context, tenantId int64, types pg.MediaType, hash string, bought bool) (m3u8.Playlist, error) {
func (svc *Service) GetM3U8(ctx context.Context, tenantId int64, types pg.MediaType, hash string, bought bool, token string) (m3u8.Playlist, error) {
log := svc.log.WithField("method", "GetM3U8")
indexPath := filepath.Join(svc.storageConfig.Path, fmt.Sprintf("%d", tenantId), hash, types.String(), "index.m3u8")
log.Infof("m3u8 path: %s", indexPath)
@@ -309,6 +335,9 @@ func (svc *Service) GetM3U8(ctx context.Context, tenantId int64, types pg.MediaT
return nil, errors.Wrap(err, "encode hash id")
}
seg.URI = fmt.Sprintf("%s/%s.%s", types, hashID, ext)
if token != "" {
seg.URI += fmt.Sprintf("?token=%s", token)
}
}
return media, nil

View File

@@ -45,15 +45,15 @@ func Test_DiscoverMedias(t *testing.T) {
func (t *ServiceTestSuite) Test_getM3U8() {
FocusConvey("Test_ffmpegVideoToM3U8", t.T(), func() {
Convey("Bought", func() {
hash := "f464a6641a60e2722e4042db8fad2813"
media, err := t.Svc.GetM3U8(context.Background(), 1, pg.MediaTypeVideo, hash, true)
hash := "907f1c8fd92704233600ae54a1d75092"
media, err := t.Svc.GetM3U8(context.Background(), 1, pg.MediaTypeVideo, hash, true, "hello")
So(err, ShouldBeNil)
t.T().Logf("%+v", media)
})
FocusConvey("Not Bought", func() {
hash := "f464a6641a60e2722e4042db8fad2813"
media, err := t.Svc.GetM3U8(context.Background(), 1, pg.MediaTypeVideo, hash, false)
hash := "907f1c8fd92704233600ae54a1d75092"
media, err := t.Svc.GetM3U8(context.Background(), 1, pg.MediaTypeVideo, hash, false, "hello")
So(err, ShouldBeNil)
t.T().Logf("%+v", media)
})

View File

@@ -1,6 +1,8 @@
package middlewares
import (
"time"
"backend/pkg/consts"
"backend/pkg/errorx"
@@ -10,14 +12,23 @@ import (
func (f *Middlewares) ParseJWT(c fiber.Ctx) error {
tokens := c.GetReqHeaders()["Authorization"]
if len(tokens) == 0 {
queryToken := c.Query("token")
tokens = []string{queryToken}
if len(tokens) == 0 {
return c.Next()
}
}
token := tokens[0]
claim, err := f.jwt.Parse(token)
if err != nil {
c.ClearCookie("token")
c.Cookie(&fiber.Cookie{
Name: "token",
Value: "",
Expires: time.Now().Add(-1 * time.Hour),
HTTPOnly: true,
})
log.Errorf("failed to parse jwt from token: %s", token)
return errorx.RequestUnAuthorized
}
@@ -26,14 +37,24 @@ func (f *Middlewares) ParseJWT(c fiber.Ctx) error {
_, err = f.userSvc.GetByOpenID(c.Context(), claim.OpenID)
if err != nil {
log.Errorf("failed to get user by open id(%s) from token: %s", claim.OpenID, token)
c.ClearCookie("token")
c.Cookie(&fiber.Cookie{
Name: "token",
Value: "",
Expires: time.Now().Add(-1 * time.Hour),
HTTPOnly: true,
})
return errorx.RequestUnAuthorized
}
_, err = f.userSvc.GetTenantBySlug(c.Context(), claim.Tenant)
if err != nil {
log.Errorf("failed to get tenant(%s) by from token: %s", claim.Tenant, token)
c.ClearCookie("token")
c.Cookie(&fiber.Cookie{
Name: "token",
Value: "",
Expires: time.Now().Add(-1 * time.Hour),
HTTPOnly: true,
})
return errorx.RequestUnAuthorized
}

View File

@@ -28,7 +28,12 @@ func (f *Middlewares) WeChatAuth(c fiber.Ctx) error {
if _, err := f.jwt.Parse(jwtToken); err != nil {
log.WithError(err).Error("failed to parse jwt token")
c.ClearCookie("token")
c.Cookie(&fiber.Cookie{
Name: "token",
Value: "",
Expires: time.Now().Add(-1 * time.Hour),
HTTPOnly: true,
})
return c.Redirect().To(c.Path())
}
}

View File

@@ -33,6 +33,5 @@ func Provide(opts ...opt.Option) error {
}); err != nil {
return err
}
return nil
}

View File

@@ -8,7 +8,7 @@ import (
"github.com/gofiber/fiber/v3"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
hashids "github.com/speps/go-hashids/v2"
"github.com/speps/go-hashids/v2"
)
// @provider
@@ -87,7 +87,7 @@ func (c *Controller) GetChargeCodes(ctx fiber.Ctx) error {
Code string `json:"code"`
}
amount := []int64{1, 5, 10, 20, 50, 100}
amount := []int64{1, 2, 5, 10, 20, 50, 100, 200, 300, 500, 1000, 2000}
codes := []generateCode{}
for _, a := range amount {
code, err := c.svc.GenerateChargeCode(ctx.Context(), claim.TenantID, a*100)

View File

@@ -7,7 +7,7 @@ import (
"git.ipao.vip/rogeecn/atom/container"
"git.ipao.vip/rogeecn/atom/contracts"
"git.ipao.vip/rogeecn/atom/utils/opt"
hashids "github.com/speps/go-hashids/v2"
"github.com/speps/go-hashids/v2"
)
func Provide(opts ...opt.Option) error {
@@ -23,7 +23,6 @@ func Provide(opts ...opt.Option) error {
}); err != nil {
return err
}
if err := container.Container.Provide(func(
controller *Controller,
) (contracts.HttpRoute, error) {
@@ -37,7 +36,6 @@ func Provide(opts ...opt.Option) error {
}, atom.GroupRoutes); err != nil {
return err
}
if err := container.Container.Provide(func(
db *sql.DB,
hashIds *hashids.HashID,
@@ -53,6 +51,5 @@ func Provide(opts ...opt.Option) error {
}); err != nil {
return err
}
return nil
}

View File

@@ -4,6 +4,7 @@ import (
"os"
"path/filepath"
"strings"
"time"
"backend/modules/users"
"backend/pkg/pg"
@@ -78,6 +79,7 @@ func (c *Controller) Render(ctx fiber.Ctx) error {
ctx.Cookie(&fiber.Cookie{
Name: "token",
Value: jwtToken,
Expires: time.Now().Add(6 * time.Hour),
HTTPOnly: true,
})

View File

@@ -27,6 +27,5 @@ func Provide(opts ...opt.Option) error {
}); err != nil {
return err
}
return nil
}

View File

@@ -26,6 +26,5 @@ func Provide(opts ...opt.Option) error {
}, atom.GroupInitial); err != nil {
return err
}
return nil
}

View File

@@ -28,7 +28,7 @@ func (c *Controller) Prepare() error {
}
func (c *Controller) store() {
ticker := time.NewTicker(time.Minute * 5)
ticker := time.NewTicker(time.Minute * 60)
for range ticker.C {
c.log.WithField("action", "store").Info("start to run store")

View File

@@ -1,41 +0,0 @@
package uuid
import (
"git.ipao.vip/rogeecn/atom/container"
"git.ipao.vip/rogeecn/atom/utils/opt"
"github.com/gofrs/uuid"
)
func DefaultProvider() container.ProviderContainer {
return container.ProviderContainer{
Provider: Provide,
Options: []opt.Option{},
}
}
type Generator struct {
generator uuid.Generator
}
func Provide(opts ...opt.Option) error {
o := opt.New(opts...)
return container.Container.Provide(func() (*Generator, error) {
return &Generator{
generator: uuid.DefaultGenerator,
}, nil
}, o.DiOptions()...)
}
func (u *Generator) MustGenerate() string {
uuid, _ := u.Generate()
return uuid
}
func (u *Generator) Generate() (string, error) {
uuid, err := u.generator.NewV4()
if err != nil {
return "", err
}
return uuid.String(), err
}

View File

@@ -4,6 +4,7 @@
exec 1>>/var/log/cron.backupdb.log 2>&1
# Add timestamp to log entry
start_time=$(date "+%Y-%m-%d %H:%M:%S")
echo "=== Backup started at $(date '+%Y-%m-%d %H:%M:%S') ==="
# Set variables
@@ -54,3 +55,12 @@ rclone sync --update /opt/services/postgres/data/backups/ alioss:/rogee-backups/
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Backup completed: postgres_backup_${TIMESTAMP}.zip"
echo "=== Backup finished at $(date '+%Y-%m-%d %H:%M:%S') ==="
end_time=$(date "+%Y-%m-%d %H:%M:%S")
/usr/bin/curl -X POST "https://gotify.jdwan.com/message?token=AknNrK_M.ZGqDz5" \
-H "Content-Type: application/json" \
-d "{
\"message\": \"Backup completed from $start_time to $end_time\",
\"title\": \"Backup Complete\",
\"priority\": 5
}"

13
cron.sh
View File

@@ -17,8 +17,17 @@ fi
start_time=$(date "+%Y-%m-%d %H:%M:%S")
echo "Start sync at $start_time" >>"$LOG_FILE"
qvyun --config /usr/local/etc/qvyun.toml tasks discover --from /mnt/ypl/publish/ --to /mnt/ypl/publish/processed/1 2>&1 >>"$LOG_FILE"
rsync -avh --progress /mnt/ypl/publish/processed/ server.ali.bj.01:/data 2>&1 >>"$LOG_FILE"
/usr/local/bin/qvyun --config /usr/local/etc/qvyun.toml tasks discover --from /mnt/ypl/publish/ --to /mnt/ypl/publish/processed/1 2>&1 >>"$LOG_FILE"
/usr/bin/rsync -avh --progress /mnt/ypl/publish/processed/ server.ali.bj.01:/data 2>&1 >>"$LOG_FILE"
end_time=$(date "+%Y-%m-%d %H:%M:%S")
echo "End sync at $end_time" >>"$LOG_FILE"
# Send notification via Gotify
/usr/bin/curl -X POST "https://gotify.jdwan.com/message?token=AknNrK_M.ZGqDz5" \
-H "Content-Type: application/json" \
-d "{
\"message\": \"Sync completed from $start_time to $end_time\",
\"title\": \"QVYun Sync Status\",
\"priority\": 5
}"

View File

@@ -9,6 +9,7 @@
"version": "0.0.0",
"dependencies": {
"axios": "^1.7.9",
"dplayer": "^1.27.1",
"hls.js": "^0.8.5",
"pinia": "^2.2.6",
"vant": "^4.9.9",
@@ -871,6 +872,12 @@
"dev": true,
"license": "MIT"
},
"node_modules/balloon-css": {
"version": "1.2.0",
"resolved": "https://npm.hub.ipao.vip/repository/npm/balloon-css/-/balloon-css-1.2.0.tgz",
"integrity": "sha512-urXwkHgwp6GsXVF+it01485Z2Cj4pnW02ICnM0TemOlkKmCNnDLmyy+ZZiRXBpwldUXO+aRNr7Hdia4CBvXJ5A==",
"license": "MIT"
},
"node_modules/binary-extensions": {
"version": "2.3.0",
"dev": true,
@@ -1108,6 +1115,28 @@
"node": ">=0.4.0"
}
},
"node_modules/dplayer": {
"version": "1.27.1",
"resolved": "https://npm.hub.ipao.vip/repository/npm/dplayer/-/dplayer-1.27.1.tgz",
"integrity": "sha512-2laBMXs5V1B9zPwJ7eAIw/OBo+Xjvy03i4GHTk3Cg+IWbrq8rKMFO0fFr6ClAYotYOCcFGOvaJDkOZcgKllsCA==",
"license": "MIT",
"dependencies": {
"axios": "1.2.3",
"balloon-css": "^1.0.3",
"promise-polyfill": "8.3.0"
}
},
"node_modules/dplayer/node_modules/axios": {
"version": "1.2.3",
"resolved": "https://npm.hub.ipao.vip/repository/npm/axios/-/axios-1.2.3.tgz",
"integrity": "sha512-pdDkMYJeuXLZ6Xj/Q5J3Phpe+jbGdsSzlQaFVkMQzRUL05+6+tetX8TV3p4HrU4kzuO9bt+io/yGQxuyxA/xcw==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.66",
"dev": true,
@@ -1997,6 +2026,12 @@
"node": "^10 || ^12 || >=14"
}
},
"node_modules/promise-polyfill": {
"version": "8.3.0",
"resolved": "https://npm.hub.ipao.vip/repository/npm/promise-polyfill/-/promise-polyfill-8.3.0.tgz",
"integrity": "sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==",
"license": "MIT"
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://npm.hub.ipao.vip/repository/npm/proxy-from-env/-/proxy-from-env-1.1.0.tgz",

View File

@@ -4,12 +4,13 @@
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"dev": "vite --host 0.0.0.0",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"axios": "^1.7.9",
"dplayer": "^1.27.1",
"hls.js": "^0.8.5",
"pinia": "^2.2.6",
"vant": "^4.9.9",

View File

@@ -1,6 +1,7 @@
<template>
<van-nav-bar :title="item.title" left-text="返回" left-arrow @click-left="onClickLeft" />
<video controls id="video" :poster="item.poster" />
<!-- <video controls id="video" :poster="item.poster" /> -->
<div id="dplayer" :style="{ backgroundImage: `url(${item.poster})` }"></div>
<template v-if="false === item.bought">
<van-notice-bar left-icon="volume-o" text="未购买的视频、音频默认播放时长为1分钟左右。" />
@@ -26,31 +27,106 @@
<script setup>
import request from "@/utils/request";
import DPlayer from "dplayer";
import Hls from "hls.js";
import { onBeforeUnmount, onMounted } from "vue";
const router = useRouter();
const route = useRoute();
const pageLoading = ref(true)
let player = null;
const item = ref({
title: "加载中...",
});
onBeforeUnmount(() => {
const player = document.getElementById("video");
if (player) {
player.pause();
}
player?.destroy();
});
onMounted(() => {
loadMedia(route.params.hash);
const player = document.getElementById("video");
player.addEventListener("ended", function () {
console.log("Video ended");
});
const onClickLeft = () => {
if (route.meta.from?.name) {
router.back();
return;
}
router.replace({
name: "tab.home",
params: {
tenant: route.params.tenant,
},
});
};
const loadMedia = (hash) => {
request
.get(`/medias/${hash}`)
.then((res) => {
console.log(res);
item.value = res.data;
})
.catch((err) => {
console.error("ERROR", err);
})
.finally(() => {
pageLoading.value = false
});
};
const play = (hash, type) => {
let source = `/v1/medias/${hash}/${type}`;
if (navigator.userAgent.indexOf("iPhone") > -1) {
source = `/v1/medias/${hash}/${type}?token=${__GA}`;
}
player = new DPlayer({
container: document.getElementById('dplayer'),
playbackSpeed: [0.5, 0.75, 1, 1.25, 1.5, 2],
video: {
url: source,
pic: item.value.poster,
type: 'customHls',
customType: {
customHls: function (video, player) {
const hls = new Hls({
xhrSetup: function (xhr, url) {
xhr.withCredentials = true;
xhr.setRequestHeader("Authorization", "Bearer " + __GA);
},
});
hls.loadSource(source);
hls.attachMedia(video);
},
},
}
});
player.play();
// if (Hls.isSupported()) {
// var hls = new Hls({
// xhrSetup: function (xhr, url) {
// xhr.withCredentials = true;
// },
// });
// hls.loadSource(source);
// hls.attachMedia(player);
// hls.on(Hls.Events.MANIFEST_PARSED, function () {
// player.play();
// });
// } else if (player.canPlayType("application/vnd.apple.mpegurl")) {
// player.src = source;
// player.addEventListener("loadedmetadata", function () {
// player.play();
// });
// }
};
const buy = () => {
// get use balance
@@ -99,55 +175,6 @@ const buy = () => {
};
const onClickLeft = () => {
if (route.meta.from?.name) {
router.back();
return;
}
router.replace({
name: "tab.home",
params: {
tenant: route.params.tenant,
},
});
};
const loadMedia = (hash) => {
request
.get(`/medias/${hash}`)
.then((res) => {
console.log(res);
item.value = res.data;
})
.catch((err) => {
console.error("ERROR", err);
})
.finally(() => {
pageLoading.value = false
});
};
const play = (hash, type) => {
const player = document.getElementById("video");
const source = `/v1/medias/${hash}/${type}`;
if (Hls.isSupported()) {
var hls = new Hls({
xhrSetup: function (xhr, url) {
xhr.setRequestHeader("Authorization", "Bearer " + __GA);
},
});
hls.loadSource(source);
hls.attachMedia(player);
hls.on(Hls.Events.MANIFEST_PARSED, function () {
player.play();
});
} else if (player.canPlayType("application/vnd.apple.mpegurl")) {
player.src = source;
player.addEventListener("loadedmetadata", function () {
player.play();
});
}
};
</script>
<style scoped>
@@ -155,10 +182,13 @@ const play = (hash, type) => {
padding: 1em;
}
#video {
#video,
#dplayer {
background-color: #cccccc;
aspect-ratio: 4 / 3;
aspect-ratio: 16 / 9;
width: 100%;
object-fit: fill;
background-size: cover;
background-position: center;
}
</style>

View File

@@ -11,7 +11,7 @@ import { defineConfig } from "vite";
export default defineConfig({
server: {
proxy: {
'^/static': {
'^/poster': {
target: 'http://localhost:9600',
changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api/, '')

View File

@@ -13,6 +13,7 @@
"settings": {
"vue3snippets.enable-compile-vue-file-on-did-save-code": false,
"cSpell.words": [
"dplayer",
"qvyun"
],
"git.ignoreLimitWarning": true