Skip to content

Instantly share code, notes, and snippets.

@lvm
Last active August 18, 2020 01:23
Show Gist options
  • Save lvm/9b031086ad26bea77323cb517cfd4eec to your computer and use it in GitHub Desktop.
Save lvm/9b031086ad26bea77323cb517cfd4eec to your computer and use it in GitHub Desktop.

Revisions

  1. lvm revised this gist Aug 18, 2020. 1 changed file with 41 additions and 4 deletions.
    45 changes: 41 additions & 4 deletions youtube-slice
    Original file line number Diff line number Diff line change
    @@ -16,7 +16,7 @@ def ffmpeg(args: list) -> None:
    sp.call(shlex.split(f"ffmpeg -v quiet -y {args}"))


    def slice_video(video_url, start, end, output="/tmp/ytslice.mp4"):
    def slice_video(video_url, start, end, output="/tmp/ytslice.mp4", intact=False):
    "Get video info and then download and slice it"
    assert video_url, "Missing video, can't continue"
    assert start, "Missing `start`, can't continue"
    @@ -33,21 +33,53 @@ def slice_video(video_url, start, end, output="/tmp/ytslice.mp4"):
    "outtmpl": f"{str(output_dir)}/%(title)s.%(ext)s"
    }

    ext = "mp4"
    if output.endswith(".mp3"):
    YTDL_OPTS.update({
    "format": "bestaudio/best",
    "postprocessors": [
    {
    "key": "FFmpegExtractAudio",
    "preferredcodec": "mp3",
    "preferredquality": "192",
    }
    ]
    })
    ext = "mp3"

    with youtube_dl.YoutubeDL(YTDL_OPTS) as ydl:
    youtube_dl.utils.std_headers["User-Agent"] = USER_AGENT
    ytdl_info = ydl.extract_info(video_url, download=False)

    title = ytdl_info.get("title")
    yt_file = sanitize_filename(title, True, False)
    yt_file = output_dir / f'{yt_file}.mp4'
    yt_file = output_dir / f'{yt_file}.{ext}'
    tmp_output = output_dir / f'{yt_file}.tmp.{ext}'
    ydl.download([video_url])
    ffmpeg(
    f"-i '{yt_file}' -ss '{start}' -to '{end}' -async 1 -acodec copy '{output}'"
    f"-i '{yt_file}' -ss '{start}' -to '{end}' -async 1 -acodec copy '{tmp_output}'"
    )

    if intact or ext == "mp3":
    Path(tmp_output).rename(output)
    else:
    ffmpeg(
    f"-i '{tmp_output}' "
    "-pix_fmt yuv420p -vcodec libx264 "
    "-vf scale=640:-1 -acodec aac -vb 1024k "
    "-minrate 1024k -maxrate 1024k -bufsize 1024k "
    "-ar 44100 -ac 2 "
    "-strict experimental -max_muxing_queue_size 1024 -r 30 "
    f"'{output}'"
    )
    Path(tmp_output).unlink()

    Path(yt_file).unlink()

    return title, output



    if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("video", type=str, default="", help="Video URL")
    @@ -65,11 +97,16 @@ if __name__ == "__main__":
    required=False,
    help="Output file (Default: /tmp/ytslice.mp4",
    )
    parser.add_argument(
    "--intact",
    action="store_true",
    help="Don't re-encode the video."
    )

    args = parser.parse_args()

    if args.video:
    title, output = slice_video(args.video, args.ss, args.to, args.output)
    title, output = slice_video(args.video, args.ss, args.to, args.output, args.intact)
    print (f"Title: {title}\nFile: {output}")
    else:
    parser.print_help()
  2. lvm revised this gist Aug 17, 2020. 1 changed file with 42 additions and 21 deletions.
    63 changes: 42 additions & 21 deletions youtube-slice
    Original file line number Diff line number Diff line change
    @@ -4,51 +4,72 @@ import shlex
    import argparse
    import youtube_dl
    import subprocess as sp
    from pathlib import Path
    from youtube_dl.utils import sanitize_filename


    def ffmpeg(args: list, verbose: bool) -> None:
    "Base ffmpeg call."
    cmd = "ffmpeg {} -y {}".format("" if verbose else "-v quiet", args)
    sp.call(shlex.split(cmd))
    USER_AGENT = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"


    def ffmpeg(args: list) -> None:
    "Base ffmpeg call."
    sp.call(shlex.split(f"ffmpeg -v quiet -y {args}"))

    def cut(_in: str, out: str, start: str, to: str, verbose: bool = False) -> None:
    "Cuts a portion of an media file."
    if isinstance(_in, (list, tuple)):
    _in = _in[0]

    ffmpeg(f"-i '{_in}' -ss '{start}' -to '{to}' -acodec copy '{out}'", verbose)
    def slice_video(video_url, start, end, output="/tmp/ytslice.mp4"):
    "Get video info and then download and slice it"
    assert video_url, "Missing video, can't continue"
    assert start, "Missing `start`, can't continue"
    assert end, "Missing `end`, can't continue"
    title = ""
    output_dir = Path(output).parent
    YTDL_OPTS = {
    "quiet": True,
    "restrictfilenames": True,
    "writethumbnail": False,
    "ignoreerrors": True,
    "geo_bypass": True,
    "format": "mp4",
    "outtmpl": f"{str(output_dir)}/%(title)s.%(ext)s"
    }

    with youtube_dl.YoutubeDL(YTDL_OPTS) as ydl:
    youtube_dl.utils.std_headers["User-Agent"] = USER_AGENT
    ytdl_info = ydl.extract_info(video_url, download=False)

    def ytdl_slice(url: str, start: str, to: str, output: str) -> None:
    "Extracts Video URL and slices it"
    with youtube_dl.YoutubeDL({"format": "best"}) as ytdl:
    result = ytdl.extract_info(url, download=False)
    video = result["entries"][0] if "entries" in result else result
    cut(video["url"], output, start, to)
    title = ytdl_info.get("title")
    yt_file = sanitize_filename(title, True, False)
    yt_file = output_dir / f'{yt_file}.mp4'
    ydl.download([video_url])
    ffmpeg(
    f"-i '{yt_file}' -ss '{start}' -to '{end}' -async 1 -acodec copy '{output}'"
    )
    Path(yt_file).unlink()

    return title, output

    if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("video", type=str, default="", help="Video URL")
    parser.add_argument(
    "-s", "--start", type=str, default="", required=True, help="Start time"
    "-ss", type=str, default="00:00:00", required=True, help="Start time"
    )
    parser.add_argument(
    "-to", "--to", type=str, default="", required=True, help="To time"
    "-to", type=str, default="", help="End time"
    )
    parser.add_argument(
    "-o",
    "--output",
    type=str,
    default="out.mp4",
    default="/tmp/ytslice.mp4",
    required=False,
    help="Output file (default: out.mp4)",
    help="Output file (Default: /tmp/ytslice.mp4",
    )

    args = parser.parse_args()

    if args.video and args.start and args.to:
    ytdl_slice(args.video, args.start, args.to, args.output)
    if args.video:
    title, output = slice_video(args.video, args.ss, args.to, args.output)
    print (f"Title: {title}\nFile: {output}")
    else:
    parser.print_help()
  3. lvm created this gist Apr 15, 2020.
    54 changes: 54 additions & 0 deletions youtube-slice
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,54 @@
    #!/usr/bin/env python3

    import shlex
    import argparse
    import youtube_dl
    import subprocess as sp


    def ffmpeg(args: list, verbose: bool) -> None:
    "Base ffmpeg call."
    cmd = "ffmpeg {} -y {}".format("" if verbose else "-v quiet", args)
    sp.call(shlex.split(cmd))


    def cut(_in: str, out: str, start: str, to: str, verbose: bool = False) -> None:
    "Cuts a portion of an media file."
    if isinstance(_in, (list, tuple)):
    _in = _in[0]

    ffmpeg(f"-i '{_in}' -ss '{start}' -to '{to}' -acodec copy '{out}'", verbose)


    def ytdl_slice(url: str, start: str, to: str, output: str) -> None:
    "Extracts Video URL and slices it"
    with youtube_dl.YoutubeDL({"format": "best"}) as ytdl:
    result = ytdl.extract_info(url, download=False)
    video = result["entries"][0] if "entries" in result else result
    cut(video["url"], output, start, to)


    if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("video", type=str, default="", help="Video URL")
    parser.add_argument(
    "-s", "--start", type=str, default="", required=True, help="Start time"
    )
    parser.add_argument(
    "-to", "--to", type=str, default="", required=True, help="To time"
    )
    parser.add_argument(
    "-o",
    "--output",
    type=str,
    default="out.mp4",
    required=False,
    help="Output file (default: out.mp4)",
    )

    args = parser.parse_args()

    if args.video and args.start and args.to:
    ytdl_slice(args.video, args.start, args.to, args.output)
    else:
    parser.print_help()