mirror of
https://github.com/crunchy-labs/crunchy-cli.git
synced 2026-01-21 12:12:00 -06:00
Moved all download related stuff to downloader.go and fixed some errors in it
This commit is contained in:
parent
d6347a6b6b
commit
6fb6b3c03c
2 changed files with 230 additions and 217 deletions
152
format.go
152
format.go
|
|
@ -1,18 +1,7 @@
|
|||
package crunchyroll
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/grafov/m3u8"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type FormatType string
|
||||
|
|
@ -56,144 +45,7 @@ func (f *Format) InitVideo() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Download downloads the Format with the via Downloader specified options
|
||||
func (f *Format) Download(downloader Downloader) error {
|
||||
if _, err := os.Stat(downloader.Filename); err == nil && !downloader.IgnoreExisting {
|
||||
return fmt.Errorf("file %s already exists", downloader.Filename)
|
||||
}
|
||||
if _, err := os.Stat(downloader.TempDir); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
err = os.Mkdir(downloader.TempDir, 0755)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if !downloader.IgnoreExisting {
|
||||
content, err := os.ReadDir(downloader.TempDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(content) > 0 {
|
||||
return fmt.Errorf("directory %s is not empty", downloader.Filename)
|
||||
}
|
||||
}
|
||||
|
||||
if downloader.DeleteTempAfter {
|
||||
defer os.RemoveAll(downloader.TempDir)
|
||||
}
|
||||
if err := download(downloader.Context, f, downloader.TempDir, downloader.Goroutines, downloader.LockOnSegmentDownload, downloader.OnSegmentDownload); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if downloader.FFmpegOpts != nil {
|
||||
return mergeSegmentsFFmpeg(downloader.Context, downloader.TempDir, downloader.Filename, downloader.FFmpegOpts)
|
||||
} else {
|
||||
return mergeSegments(downloader.Context, downloader.TempDir, downloader.Filename)
|
||||
}
|
||||
}
|
||||
|
||||
// mergeSegments reads every file in tempDir and writes their content to the outputFile.
|
||||
// The given output file gets created or overwritten if already existing
|
||||
func mergeSegments(context context.Context, tempDir string, outputFile string) error {
|
||||
dir, err := os.ReadDir(tempDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file, err := os.OpenFile(outputFile, os.O_CREATE|os.O_WRONLY, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
writer := bufio.NewWriter(file)
|
||||
defer writer.Flush()
|
||||
|
||||
// sort the directory files after their numeric names
|
||||
sort.Slice(dir, func(i, j int) bool {
|
||||
iNum, err := strconv.Atoi(strings.Split(dir[i].Name(), ".")[0])
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
jNum, err := strconv.Atoi(strings.Split(dir[j].Name(), ".")[0])
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return iNum < jNum
|
||||
})
|
||||
|
||||
for _, file := range dir {
|
||||
select {
|
||||
case <-context.Done():
|
||||
return context.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
bodyAsBytes, err := ioutil.ReadFile(filepath.Join(tempDir, file.Name()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = writer.Write(bodyAsBytes); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// mergeSegmentsFFmpeg reads every file in tempDir and merges their content to the outputFile
|
||||
// with ffmpeg (https://ffmpeg.org/).
|
||||
// The given output file gets created or overwritten if already existing
|
||||
func mergeSegmentsFFmpeg(context context.Context, tempDir string, outputFile string, opts []string) error {
|
||||
dir, err := os.ReadDir(tempDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f, err := os.Create(filepath.Join(tempDir, "list.txt"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// -1 is the list.txt file
|
||||
for i := 0; i < len(dir)-1; i++ {
|
||||
fmt.Fprintf(f, "file '%s.ts'\n", filepath.Join(tempDir, strconv.Itoa(i)))
|
||||
}
|
||||
f.Close()
|
||||
|
||||
// predefined options ... custom options ... predefined output filename
|
||||
command := []string{
|
||||
"-y",
|
||||
"-f", "concat",
|
||||
"-safe", "0",
|
||||
"-i", f.Name(),
|
||||
"-c", "copy",
|
||||
}
|
||||
if opts != nil {
|
||||
command = append(command, opts...)
|
||||
}
|
||||
command = append(command, outputFile)
|
||||
|
||||
var errBuf bytes.Buffer
|
||||
cmd := exec.Command("ffmpeg",
|
||||
command...)
|
||||
cmd.Stderr = &errBuf
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmdChan := make(chan error, 1)
|
||||
go func() {
|
||||
cmdChan <- cmd.Wait()
|
||||
}()
|
||||
|
||||
select {
|
||||
case err = <-cmdChan:
|
||||
if err != nil {
|
||||
if errBuf.Len() > 0 {
|
||||
return fmt.Errorf(errBuf.String())
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
case <-context.Done():
|
||||
cmd.Process.Kill()
|
||||
return context.Err()
|
||||
}
|
||||
return downloader.download(f)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue