Use a CDN for faster AMV delivery
This commit is contained in:
72
arn/AMV.go
72
arn/AMV.go
@ -3,6 +3,7 @@ package arn
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
@ -10,6 +11,7 @@ import (
|
||||
|
||||
"github.com/aerogo/nano"
|
||||
"github.com/animenotifier/notify.moe/arn/video"
|
||||
"github.com/minio/minio-go/v6"
|
||||
)
|
||||
|
||||
// AMV is an anime music video.
|
||||
@ -36,16 +38,37 @@ func (amv *AMV) Link() string {
|
||||
return "/amv/" + amv.ID
|
||||
}
|
||||
|
||||
// VideoLink returns the permalink for the video file.
|
||||
func (amv *AMV) VideoLink() string {
|
||||
domain := "arn.sfo2.cdn"
|
||||
|
||||
if amv.IsDraft {
|
||||
domain = "arn.sfo2"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("https://%s.digitaloceanspaces.com/videos/amvs/%s", domain, amv.File)
|
||||
}
|
||||
|
||||
// TitleByUser returns the preferred title for the given user.
|
||||
func (amv *AMV) TitleByUser(user *User) string {
|
||||
return amv.Title.ByUser(user)
|
||||
}
|
||||
|
||||
// SetVideoBytes sets the bytes for the video file.
|
||||
func (amv *AMV) SetVideoBytes(data []byte) error {
|
||||
// SetVideoReader sets the bytes for the video file by reading them from the reader.
|
||||
func (amv *AMV) SetVideoReader(reader io.Reader) error {
|
||||
fileName := amv.ID + ".webm"
|
||||
filePath := path.Join(Root, "videos", "amvs", fileName)
|
||||
err := ioutil.WriteFile(filePath, data, 0644)
|
||||
pattern := amv.ID + ".*.webm"
|
||||
file, err := ioutil.TempFile("", pattern)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
filePath := file.Name()
|
||||
defer os.Remove(filePath)
|
||||
|
||||
// Write file contents
|
||||
_, err = io.Copy(file, reader)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
@ -53,6 +76,7 @@ func (amv *AMV) SetVideoBytes(data []byte) error {
|
||||
|
||||
// Run mkclean
|
||||
optimizedFile := filePath + ".optimized"
|
||||
defer os.Remove(optimizedFile)
|
||||
|
||||
cmd := exec.Command(
|
||||
"mkclean",
|
||||
@ -79,37 +103,35 @@ func (amv *AMV) SetVideoBytes(data []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Now delete the original file and replace it with the optimized file
|
||||
err = os.Remove(filePath)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = os.Rename(optimizedFile, filePath)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Refresh video file info
|
||||
amv.File = fileName
|
||||
return amv.RefreshInfo()
|
||||
}
|
||||
info, err := video.GetInfo(optimizedFile)
|
||||
|
||||
// RefreshInfo refreshes the information about the video file.
|
||||
func (amv *AMV) RefreshInfo() error {
|
||||
if amv.File == "" {
|
||||
return fmt.Errorf("Video file has not been uploaded yet for AMV %s", amv.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
info, err := video.GetInfo(path.Join(Root, "videos", "amvs", amv.File))
|
||||
// Is our storage server available?
|
||||
if Spaces == nil {
|
||||
return errors.New("File storage client has not been initialized")
|
||||
}
|
||||
|
||||
// Make sure the file is public
|
||||
userMetaData := map[string]string{
|
||||
"x-amz-acl": "public-read",
|
||||
}
|
||||
|
||||
// Upload the file to our storage server
|
||||
_, err = Spaces.FPutObject("arn", fmt.Sprintf("videos/amvs/%s.webm", amv.ID), optimizedFile, minio.PutObjectOptions{
|
||||
ContentType: "video/webm",
|
||||
UserMetadata: userMetaData,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
amv.Info = *info
|
||||
amv.File = fileName
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,6 @@ package arn
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
|
||||
"github.com/aerogo/aero"
|
||||
@ -104,8 +102,8 @@ func (amv *AMV) Delete() error {
|
||||
}
|
||||
|
||||
// Remove file
|
||||
if amv.File != "" {
|
||||
err := os.Remove(path.Join(Root, "videos", "amvs", amv.File))
|
||||
if amv.File != "" && Spaces != nil {
|
||||
err := Spaces.RemoveObject("arn", fmt.Sprintf("videos/amvs/%s", amv.File))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -117,4 +117,7 @@ func init() {
|
||||
// Set Anilist API keys
|
||||
anilist.APIKeyID = APIKeys.AniList.ID
|
||||
anilist.APIKeySecret = APIKeys.AniList.Secret
|
||||
|
||||
// Initialize file storage
|
||||
initSpaces()
|
||||
}
|
||||
|
30
arn/Spaces.go
Normal file
30
arn/Spaces.go
Normal file
@ -0,0 +1,30 @@
|
||||
package arn
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/minio/minio-go/v6"
|
||||
)
|
||||
|
||||
// Spaces represents our file storage server.
|
||||
var Spaces *minio.Client
|
||||
|
||||
// initSpaces starts our file storage client.
|
||||
func initSpaces() {
|
||||
if APIKeys.S3.ID == "" || APIKeys.S3.Secret == "" {
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
var err error
|
||||
endpoint := "sfo2.digitaloceanspaces.com"
|
||||
ssl := true
|
||||
|
||||
// Initiate a client using DigitalOcean Spaces.
|
||||
Spaces, err = minio.New(endpoint, APIKeys.S3.ID, APIKeys.S3.Secret, ssl)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
}
|
Reference in New Issue
Block a user