github.com/0chain/gosdk@v1.17.11/zboxcore/sdk/live_upload_reader_youtubedl.go (about)

     1  package sdk
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"os/exec"
     9  	"strconv"
    10  	"strings"
    11  )
    12  
    13  // YoutubeDL wrap youtube-dl to download video from youtube
    14  type YoutubeDL struct {
    15  	ctx context.Context
    16  
    17  	liveUploadReaderBase
    18  
    19  	// cmdYoutubeDL youtube-dl command
    20  	cmdYoutubeDL *exec.Cmd
    21  
    22  	// cmdFfmpeg ffmpeg command
    23  	cmdFfmpeg *exec.Cmd
    24  }
    25  
    26  // CreateYoutubeDL create a youtube-dl instance to download video file from youtube
    27  //   - localPath: output file path
    28  //   - feedURL: youtube video url
    29  //   - downloadArgs: youtube-dl download arguments
    30  //   - ffmpegArgs: ffmpeg arguments
    31  //   - delay: delay in seconds
    32  func CreateYoutubeDL(ctx context.Context, localPath string, feedURL string, downloadArgs []string, ffmpegArgs []string, delay int) (*YoutubeDL, error) {
    33  
    34  	//youtube-dl -f best https://www.youtube.com/watch?v=RfUVIwnsvS8 --proxy http://127.0.0.1:8000 -o - | ffmpeg -i - -flags +cgop -g 30 -hls_time 5 youtube.m3u8
    35  
    36  	builder := createFileNameBuilder(localPath)
    37  
    38  	argsYoutubeDL := append(downloadArgs,
    39  		"-o", "-",
    40  		feedURL) //output to stdout
    41  
    42  	//argsYoutubeDL = append(argsYoutubeDL)
    43  
    44  	fmt.Println("[cmd]", "youtube-dl", strings.Join(argsYoutubeDL, " "))
    45  
    46  	r, w := io.Pipe()
    47  
    48  	cmdYoutubeDL := exec.Command("youtube-dl", argsYoutubeDL...)
    49  	cmdYoutubeDL.Stderr = os.Stderr
    50  	cmdYoutubeDL.Stdout = w
    51  
    52  	argsFfmpeg := []string{"-i", "-"}
    53  
    54  	argsFfmpeg = append(argsFfmpeg, ffmpegArgs...)
    55  	argsFfmpeg = append(argsFfmpeg,
    56  		"-flags", "+cgop",
    57  		"-g", "30",
    58  		"-hls_time", strconv.Itoa(delay),
    59  		builder.OutFile())
    60  
    61  	fmt.Println("[cmd]ffmpeg", strings.Join(argsFfmpeg, " "))
    62  	cmdFfmpeg := exec.Command("ffmpeg", argsFfmpeg...)
    63  	cmdFfmpeg.Stderr = os.Stderr
    64  	cmdFfmpeg.Stdin = r
    65  	cmdFfmpeg.Stdout = os.Stdout
    66  
    67  	err := cmdYoutubeDL.Start()
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	err = cmdFfmpeg.Start()
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  
    77  	dl := &YoutubeDL{
    78  		ctx: ctx,
    79  		liveUploadReaderBase: liveUploadReaderBase{
    80  			builder:    builder,
    81  			delay:      delay,
    82  			clipsIndex: 0,
    83  		},
    84  		cmdYoutubeDL: cmdYoutubeDL,
    85  		cmdFfmpeg:    cmdFfmpeg,
    86  	}
    87  
    88  	go dl.wait()
    89  
    90  	return dl, nil
    91  }
    92  
    93  func (r *YoutubeDL) wait() {
    94  
    95  	go func() {
    96  		<-r.ctx.Done()
    97  		r.Close()
    98  	}()
    99  
   100  	go func() {
   101  		r.err = r.cmdFfmpeg.Wait()
   102  	}()
   103  
   104  	r.err = r.cmdYoutubeDL.Wait()
   105  }
   106  
   107  // Close implements io.Closer
   108  func (r *YoutubeDL) Close() error {
   109  	if r != nil {
   110  		if r.cmd != nil {
   111  			r.cmd.Process.Kill() //nolint
   112  		}
   113  
   114  		if r.cmdYoutubeDL != nil {
   115  			r.cmdYoutubeDL.Process.Kill() //nolint
   116  		}
   117  
   118  		if r.cmdFfmpeg != nil {
   119  			r.cmdFfmpeg.Process.Kill() //nolint
   120  		}
   121  
   122  		if r.clipsReader != nil {
   123  			r.clipsReader.Close()
   124  		}
   125  	}
   126  
   127  	return nil
   128  }