Downloading streams

Toxteth

Active member
There are usually ways around that. Either dive into the page source and find a link to the MP4 directly, or if they serve an M3U8 file, install FFmpeg and (after some frustration trying to discover/google the command line options you need) feed the URL of the M3U8 to that and it will download the video plus convert it to whatever format and/or dimensions you want. I've not come across many sites on which you can't download at all. There have been one or two on which I couldn't find a way, but >99% will work with one of these methods.
Thank you Toxteth, I'll definitely look into it.
I thought I'd expand a little on what I meant. I'm sure there are easier ones, but this one works for me. I arrived at this after some abortive starts with various download software, so I ended up using FFmpeg in the terminal on my Mac, and then writing a script to make that easier.

Preparation​

What you need is the following:
  • FFmpeg, which is a program that can do just about everything you want with video files short of playing them.
  • Python, a programming language.
If you're on a Linux box or a Mac, Python will be installed already, but on Windows you'll have to install it yourself. FFmpeg is likely to not be on your computer at all; Linux users can get it through their favorite package manager, Mac users are best off installing Homebrew and then using that to install the FFmpeg formula. Windows users: see the FFmpeg downloads page.

Next, copy this script (select it and then click on the Edit menu and Copy):
Code:
#! /usr/bin/env python3	# You may need to adjust this to match the python executable on your computer -- such as plain `python' instead of `python3'
# -*- coding: utf-8 -*-

import argparse, os, sys

parser = argparse.ArgumentParser(description='Downloads a stream to an mp4 file')

parser.add_argument("-a", metavar="NAME", action="append", help="Name of an actor; will be added after scene number; can be specified more than once")

parser.add_argument("-b", metavar="[[hh:]mm:]ss", help="Time in stream at which to begin download (defaults to 00:00:00)")

parser.add_argument("-d", action="store_true", default=False, help="Dry run -- don't actually download anything but print the command that would be sent to ffmpeg")

parser.add_argument("-e", metavar="[[hh:]mm:]ss", help="Time in stream at which to end download (defaults to end of video)")

parser.add_argument("-n", type=int, metavar="NUMBER", help="Number of desired stream in the M3U8 file (first is 0)")

parser.add_argument("-s", type=int, metavar="NUMBER", help="Scene number; will be added after filename")

parser.add_argument("-p", metavar="NAME", help="Name of publisher/studio/etc.; will be added after name of actors")

parser.add_argument("-x", metavar="[.]EXTENSION", default="mp4", help="Extension for desired type of file for output (default: mp4); see FFmpeg documentation for which is which")

parser.add_argument("-y", metavar="YEAR", help="Year in which video was released; will be added at end of filename")

parser.add_argument("url", help="URL of stream to download")

parser.add_argument("file", help="name of file to output")


def secondsToTime(seconds):
	"""Converts a number of seconds to [hh:]mm:ss."""
	if seconds > 3600:
		hours = seconds // 3600		# // is int(/)
		seconds = seconds % 3600
		minutes = seconds // 60
		seconds = seconds % 60
		return "{0}:{1}:{2}".format(hours, minutes, seconds)
	elif seconds > 60:
		minutes = seconds // 60
		seconds = seconds % 60
		return "{0}:{1}".format(minutes, seconds)
	else:
		minutes = 0
		return "0:{0}".format(seconds)


if len(sys.argv) == 1:
	sys.argv.append("-h")


args = parser.parse_args()

ffmpeg = "ffmpeg"

if args.b:	# Time of beginning of download
	if ":" in args.b:
		beginTime = args.b
	else:
		beginTime = secondsToTime(int(args.b))
	ffmpeg += " -ss " + beginTime

if args.e:	# Time of end of download
	if ":" in args.e:
		endTime = args.e
	else:
		endTime = secondsToTime(int(args.e))
	ffmpeg += " -to " + endTime

ffmpeg += " -i \"" + args.url + "\""	# URL of m3u8 file

if args.n:	# Number of stream in m3u8 file
	ffmpeg += " -map p:" + str(args.n)

ffmpeg += " -c copy \"" + args.file	# Local filename

if args.s:	# Number of scene in movie
	ffmpeg += " scene " + str(args.s)

if args.a:	# Names of actors
	actors = " & ".join(args.a)
	actors = actors.replace(" & ", ", ", actors.count(" & ") - 1)
	ffmpeg += " (" + actors + ")"

if args.p or args.y:	# Name of publisher/studio and Year in which movie was released
	t = []
	if args.p:
		t.append(str(args.p))
	if args.y:
		t.append(str(args.y))

	if len(t):
		ffmpeg += " [" + ", ".join(t) + "]"

if args.x[0] != ".":	# Make sure there's a dot before the file extension
	ffmpeg += "."

ffmpeg += args.x + "\""	# File extension

if args.d:
	print(ffmpeg)
else:
	os.system(ffmpeg)	# Let's download!

Open a text editor, like Windows Notepad or macOS Text Edit and paste the script into an empty document. Save it as a plain text file (this is important) with any name you like — I called it mp4download.py. On a Linux box or a Mac, you will want to make the saved file executable with the terminal command chmod +x /path/to/mp4download.py — in which, of course, you replace "/path/to/mp4download.py" with the actual path and filename to the file you saved.

You only need to do the above once. When it's done, you can use the script to download pretty much any stream you like.
 

Using It​

To use the script, you will need to run it. On Linux and macOS, you do that by opening the terminal, typing cd /path/to/ (that is, the same path as above) and pressing the Return key, which puts you in the folder where you saved the script. Under Windows, open a DOS window and type cd \path\to\ instead, followed by the Return key again. Once there, on Linux or a Mac, now type ./mp4download.py (tip: type just an m or mp and press the Tab key, it should autocomplete to the full name), on Windows, type python mp4download.py instead; press the Return key afterward in either case.

The output should be an overview of the script's options, like so:
Code:
usage: mp4download.py [-h] [-a NAME] [-b [[hh:]mm:]ss] [-d] [-e [[hh:]mm:]ss] [-y YEAR] [-n NUMBER] [-s NUMBER] [-p NAME] [-x [.]EXTENSION] url file

Downloads a stream to an mp4 file

positional arguments:
  url              URL of stream to download
  file             name of file to output

options:
  -h, --help       show this help message and exit
  -a NAME          Name of an actor; will be added after scene number; can be specified more than once
  -b [[hh:]mm:]ss  Time in stream at which to begin download (defaults to 00:00:00)
  -d               Dry run -- don't actually download anything but print the command that would be sent to ffmpeg
  -e [[hh:]mm:]ss  Time in stream at which to end download (defaults to end of video)
  -y YEAR          Year in which video was released; will be added at end of filename
  -n NUMBER        Number of desired stream in the M3U8 file (first is 0)
  -s NUMBER        Scene number; will be added after filename
  -p NAME          Name of publisher/studio/etc.; will be added after name of actors
  -x [.]EXTENSION  Extension for desired type of file for output (default: mp4); see FFmpeg documentation for which is which
  -y YEAR          Year in which video was released; will be added at end of filename

This shows it's working — if you don't tell it which file to download, it will give this help message. To actually download a file, you need to find its URL. For M3U8 files, you can do this by opening your browser's developers tools – right-click somewhere on the page (but not on the video) and from the menu that appears, choose to inspect the element. In the window that appears, go to the Network tab and type m3u8 into the search field (if there are no results, reload the page; if there still are no results, it’s not an m3u8 stream).

Assuming there are results, find master.m3u8 in the list of files and right-click it, then find the option to copy the URL.

Then go to the terminal again, type the command to start mp4download.py (as above), but don't press Return. Instead, follow with a space and a double quote mark (", then paste the URL and type another double quote mark. The type another space and the title you want the video file to have when it's saved on your system; it's best to also enclose that in double quote marks. Now press Return, and the script will start FFmpeg and tell it to download the stream, then save it with the filename you specified. For example:

Code:
./mp4download.py "https://trailer.adultempire.com/hls/previewscene/4666925/1633954/master.m3u8" "Sexy Brunette Lesbians Fuck Each Other"
(OK, so that's a trailer, but it serves to illustrate the way this works :) )


Options​

You can use the options for the script to specify more details. To use these, after the filename you type a space and then a hyphen (-) followed by the letter of the option you want, then another space and the value for it. For example, if I want the filename to include the names of the actresses from the trailer above, I would add -a "Aubry Babcock" -a "Katie Kush" after the filename. The other options work just like that. Be sure to put a quote marks around everything that includes spaces, such as the names above; if there is no space, like in a year or someone with only a single name, you don't need the quotes: -y 2019 or -p Bangbros will work fine, but -p Team Skeet will cause problems because it will take "Team" to be the publisher's name and then say it won't know what to do with "Skeet": mp4download.py: error: unrecognized arguments: Skeet.

You can specify the beginning and end times, like if you want to download only a specific section of a longer file, with the -b and -e options. The times can be in seconds, minutes and seconds, or hours, minutes and seconds: -b 600 is the same as -b 10:00, for example. The first just says you want it to begin at 600 seconds from the start, the second at 10 minutes and 0 seconds.




Yes, this may seem like a bit of a hassle if you're not used to using the terminal. But it works, it's flexible and once you've done it a few times, it will be quick and simple :)
 
Last edited:
Ever considered the Video Download Helper plugin?
You just have to press "play" and it will detect the video and you can download it.

Or do you have this script for when such a plugin does not work?
 
Back
Top