123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- package storageproviders
- import (
- "os"
- "path/filepath"
- "sort"
- "github.com/pkg/errors"
- log "github.com/sirupsen/logrus"
- "github.com/owncast/owncast/config"
- "github.com/owncast/owncast/core/data"
- )
- // LocalStorage represents an instance of the local storage provider for HLS video.
- type LocalStorage struct {
- host string
- }
- // NewLocalStorage returns a new LocalStorage instance.
- func NewLocalStorage() *LocalStorage {
- return &LocalStorage{}
- }
- // Setup configures this storage provider.
- func (s *LocalStorage) Setup() error {
- s.host = data.GetVideoServingEndpoint()
- return nil
- }
- // SegmentWritten is called when a single segment of video is written.
- func (s *LocalStorage) SegmentWritten(localFilePath string) {
- if _, err := s.Save(localFilePath, 0); err != nil {
- log.Warnln(err)
- }
- }
- // VariantPlaylistWritten is called when a variant hls playlist is written.
- func (s *LocalStorage) VariantPlaylistWritten(localFilePath string) {
- if _, err := s.Save(localFilePath, 0); err != nil {
- log.Errorln(err)
- return
- }
- }
- // MasterPlaylistWritten is called when the master hls playlist is written.
- func (s *LocalStorage) MasterPlaylistWritten(localFilePath string) {
- // If we're using a remote serving endpoint, we need to rewrite the master playlist
- if s.host != "" {
- if err := rewritePlaylistLocations(localFilePath, s.host, ""); err != nil {
- log.Warnln(err)
- }
- } else {
- if _, err := s.Save(localFilePath, 0); err != nil {
- log.Warnln(err)
- }
- }
- }
- // Save will save a local filepath using the storage provider.
- func (s *LocalStorage) Save(filePath string, retryCount int) (string, error) {
- return filePath, nil
- }
- func (s *LocalStorage) Cleanup() error {
- // Determine how many files we should keep on disk
- maxNumber := data.GetStreamLatencyLevel().SegmentCount
- buffer := 10
- baseDirectory := config.HLSStoragePath
- files, err := getAllFilesRecursive(baseDirectory)
- if err != nil {
- return errors.Wrap(err, "unable find old video files for cleanup")
- }
- // Delete old private HLS files on disk
- for directory := range files {
- files := files[directory]
- if len(files) < maxNumber+buffer {
- continue
- }
- filesToDelete := files[maxNumber+buffer:]
- log.Traceln("Deleting", len(filesToDelete), "old files from", baseDirectory, "for video variant", directory)
- for _, file := range filesToDelete {
- fileToDelete := filepath.Join(baseDirectory, directory, file.Name())
- err := os.Remove(fileToDelete)
- if err != nil {
- return errors.Wrap(err, "unable to delete old video files")
- }
- }
- }
- return nil
- }
- func getAllFilesRecursive(baseDirectory string) (map[string][]os.FileInfo, error) {
- files := make(map[string][]os.FileInfo)
- var directory string
- err := filepath.Walk(baseDirectory, func(path string, info os.FileInfo, err error) error {
- if err != nil {
- return err
- }
- if info.IsDir() {
- directory = info.Name()
- }
- if filepath.Ext(info.Name()) == ".ts" {
- files[directory] = append(files[directory], info)
- }
- return nil
- })
- if err != nil {
- return nil, err
- }
- // Sort by date so we can delete old files
- for directory := range files {
- sort.Slice(files[directory], func(i, j int) bool {
- return files[directory][i].ModTime().UnixNano() > files[directory][j].ModTime().UnixNano()
- })
- }
- return files, nil
- }
|