Modular Movie, TV, and Music Archival Software
this
variable, not self
__version__
variable forgot to be updatedget_profiles()
methodrequests
, that makes HTTP(S) calls using Python-requests.curl_impersonate
, that makes HTTP(S) calls using Curl-Impersonate via Curl_CFFI.EXT-X-DISCONTINUITY
are now supported.urn:tva:metadata:cs:AudioPurposeCS:2007 = 2
.--audio-only/--subs-only/--chapters-only
flags can now be used simultaneously. For example, --subs-only
with --chapters-only
will get just Subtitles and Chapters.--video-only
flag, which can also still be simultaneously used with the only "only" flags. Using all four
of these flags will have the same effect as not using any of them.--no-proxy
flag, disabling all uses of proxies, even if --proxy
is set.--sub-format
option, which sets the wanted output subtitle format, defaulting to SubRip (SRT).Subtitle.reverse_rtl()
method to use SubtitleEdit's /ReverseRtlStartEnd
functionality.Subtitle.convert()
method to convert the loaded Subtitle to another format. Note that you cannot convert to
fTTML or fVTT, but you can convert from them. SubtitleEdit will be used in precedence over pycaption if available.
Converting to SubStationAlphav4 requires SubtitleEdit, but you may want to manually alter the Canvas resolution after
the download.Subtitle.parse()
via pycaption.API
Vault Client aiming for a RESTful like API.Chapters
Class to hold the new reworked Chapter
objects, automatically handling stuff like order of the
Chapters, Chapter numbers, loading from a chapter file or string, and saving to a chapter file or string.chapter_fallback_name
config option allowing you to set a Chapter Name Template used when muxing Chapters
into an MKV Container with MKVMerge. Do note, it defaults to no Chapter Fallback Name at all, but MKVMerge will force
Chapter {i:02}
at least for me on Windows with the program language set to English. You may want to instead use
Chapter {j:02}
which will do Chapter 01, Intro, Chapter 02
instead of Chapter 01, Intro, Chapter 03
(an Intro
is not a Chapter of story, but it is the 2nd Chapter marker, so It's up to you how you want to interpret it).Track.OnSegmentDownloaded
Event, called any time one of the Track's segments were downloaded.Subtitle.OnConverted
Event, called any time that Subtitle is converted.__add__
method to Tracks
class, allowing you to add to the first Tracks object. For example, making
it handy to merge HLS video tracks with DASH tracks, tracks = dash_tracks + hls_tracks.videos
, or for iterating:
for track in dash.videos + hls.videos: ...
.get_free_port()
to get a free local port to use, though it may be taken by the time it's used.rlaphoenix-pymp4
) back to the original pymp4
release as it is
now up-to-date with some of my needed fixes.url
property to be reused by DASH.download_track()
.“
and ”
) are now stripped from filenames.:ERROR:
log message) it will now raise a subprocess.CalledProcessError
exception, even if the process return code is 0.MULTI-LANGUAGE SRT
header forcefully removed. The root cause of the error
was identified and fixed in this release.Range.Transfer.SDR_BT_601_625 = 5
has been removed, Range.from_cicp()
now internally remaps CICP transfer
values of 5
to 6
(which is now Range.Transfer.BT_601 = 6
).--referer
and
--user-agent
options respectively, instead of --header
.-j
, -x
, and -s
option values can now be set by the config under the aria2c
key in the options'
full names.-x
, and -s
option values now use aria2(c)'s own default values for them instead of 16
. The j
option value defaults to ThreadPoolExecutor's algorithm of min(32,(cpu_count+4))
.LICENSING
on the speed text when licensing DRM, and LICENSED
once finished.CANCELLING
/CANCELLED
on the speed text when cancelling downloads. This is to
make it more clear that it didn't just stop, but stopped as it was cancelled.constants.py
so it can be used across the codebase easier without
argument drilling. DL_POOL_STOP
was renamed to DOWNLOAD_CANCELLED
and DL_POOL_SKIP
to DOWNLOAD_LICENCE_ONLY
.Track.repackage()
now saves as {name}_repack.{ext}
instead of {name}.repack.{ext}
.Video.change_color_range()
now saves as {name}_{limited|full}_range.{ext}
instead of {name}.range{0|1}.{ext}
.Widevine.decrypt()
now saves as {name}_decrypted.{ext}
instead of {name}.decrypted.{ext}
.MP4
when calling shaka-packager
.requests
instead of aria2c
to reduce required external dependencies.Chapter
class to only hold a timestamp and name value with an ID automatically generated as a CRC32 of
the Chapter representation.--group
option has been renamed to --tag
.%appdata%/Python/Python311/site-packages/devine/devine.yaml
).%appdata%/Python/Python311/site-packages/devine.yaml
).%localappdata%/devine/devine.yaml
).
Location 2 allows having a config at the root of a portable folder.-p/--profile
and the profile exists./ConvertColorsToDialog
option.ffmpeg
. Doing the final merge by byte concatenation did not work for some playlists.rich
's Progress.update()
method.
DASH and HLS now pass the yielded information to their progress callable instead of passing the progress callable to
the downloader.pproxy
by a subprocess instead of the now-removed
start_pproxy
utility. This way has proven to be easier, more reliable, and prevents pproxy from messing with rich's
terminal output in strange ways.uri
to urls
, out
(path) was removed,
we now calculate the save path by passing an output_dir
and filename
. The silent
, segmented
, and progress
parameters were completely removed.urls
can now be a string or a dictionary containing extra URL-specific options to use like
URL-specific headers. It can also be a list of the two types of URLs to downloading multi-threaded.filenames
can be a static string, or a filename string template with a few variables to use. The
template system used is f-string, e.g., "file_{i:03}{ext}"
(ext starts with .
if there's an extension).Widevine.decrypt()
method now also searches for shaka-packager as just packager
as it is the default build
name. (#74)devine auth
command and sub-commands due to lack of support, risk of data, and general quirks with it.profiles
config, you must now specify which profile you wish to use each time with -p/--profile
. If you
use a specific profile a lot more than others, you should make it the default.saldl
downloader has been removed as their binary distribution is whack and development has seemed to stall.
It was only used as an alternative to what was at the time the only downloader, aria2(c), as it did not support any
form of Byte Range, but saldl
did, which was crucial for resuming extremely large downloads or complex playlists.
However, now we have the requests downloader which does support the Range header.Track.needs_proxy
property was removed for a few design architectural reasons.
--proxy 127.0.0.1:8080
, I would expect it to use that proxy for all
communication indefinitely, not switch in and out depending on the track or service.Range.Transfer.SDR_BT_601_625 = 5
key and value has been removed as I cannot find any official source to verify
it as the correct use. However, usually a transfer
value of 5
would be PAL SD material so it better matches 6
,
which is (now named) Range.Transfer.BT_601 = 6
. If you have something specifying transfer=5, just remap it to 6.There's no ... Audio Tracks, likely part of an invariant playlist, continuing...
message has been
removed. So long as your playlist is expecting no audio tracks, or the audio is part of the video transport, then
this wouldn't be a problem whatsoever. Therefore, having it log this annoying warning all the time is pointless.--min-split-size
argument to the aria2(c) downloader as it was only used to disable splitting on
segmented downloads, but the newer downloader system wouldn't really need or want this to be done. If aria2 has
decided based on its other settings to have split a segment file, then it likely would benefit from doing so.--remote-time
argument from the aria2(c) downloader as it may need to do a GET and a HEAD request to
get the remote time information, slowing the download down. We don't need this information anyway as it will likely
be repacked with ffmpeg
or multiplexed with mkvmerge
, discarding/losing that information.start_pproxy
utility has been removed as all uses of it now call pproxy
via subprocess instead.LANGUAGE_MUX_MAP
constant and it's usage has been removed as it is no longer necessary as of MKVToolNix v54.__ALL__
with Class objects have been correct to __all__
with string objects, following PEP8.Track.get_key_id()
as it was a tuple rather than the URL string.--skip-dl
flag now works again after breaking in v[1.3.0].wvd add
command.Content-Length
header with a value of 0
or smaller.Subtitle.parse()
. This stopped conversions to SRT
containing the MULTI-LANGUAGE SRT
header when there was multiple caption lists, even though only one of them
actually contained captions.Subtitle.parse()
.‎
and ‏
HTML entities unescaped post-download as some rendering
libraries seems to not decode them for us. SubtitleEdit also has problems with /ReverseRtlStartEnd
unless it's
already decoded.../
.Newly added to x/y Vaults
log, which now states Cached n Key(s) to x/y Vaults
.Since -q/--quality
has been reworked to support specifying multiple qualities, the type of this value is
no longer None|int
. It is now list[int]
and the list may be empty. It is no longer ever a None
value.
Please make sure any Service code that uses quality
via ctx.parent.params
reflects this change. You may
need to go from an if quality: ...
to for res in quality: ...
, or such. You may still use if quality
to check if it has 1 or more resolution specified, but make sure that the code within that if tree supports
more than 1 value in the quality
variable, which is now a list. Note that the list will always be in
descending order regardless of how the user specified them.
-q/--quality
. E.g., -q 1080p,720p
.uuid
mp4 boxes containing tenc
box data when getting the Track's Key ID to improve
chances of finding a Key ID.with_resolution
method in the Tracks class. It has been replaced with by_resolutions
. The
new replacement method supports getting all or n amount of tracks by resolution instead of the original
always getting all tracks by resolution.select_per_language
method in the Tracks class. It has been replaced with by_language
. The
new replacement method supports getting all or n amount of tracks by language instead of the original only
able to get one track by language. It now defaults to getting all tracks by language.tenc
mp4 boxes when obtaining the track's Key ID by using my own fork of pymp4
with up-to-date code and further fixes.tenc
mp4 boxes by simply skipping tenc
boxes that fail to parse. This happens
because some services seem to mix up the data of the tenc
box with that of another type of box.tenc
boxes by skipping ones with a version number greater than 1.0-20000
(where 20000 is the default maximum_size
). It now also checks if the
server supports Byte-range, or it will otherwise stream the response. It also tries to get the file size length and
uses that instead of maximum_size
unless it's bigger than maximum_size
.get_key_id
method to Track to probe the track for a track-specific Encryption Key ID. This is similar to
Widevine's from_track
method but ignores all pssh
boxes and manifest information as the information within those
could be for a wider range of tracks or not for that track at all.audio_en=128000
would be an English audio track at 128kb/s. We now take the en
from that ID where possible.forced-subtitle
and forced_subtitle
(#43).*
symbol is no longer spaced after the Widevine KID:KEY
when denoting that it is for this specific PSSH.
This reduces wasted vertical space.*
symbol that indicates that the KID:KEY is for the track being downloaded now uses the new get_key_id
method
of the track for a more accurate reading.--cdm-only
is used.CEKNotFound
and EmptyLicense
.get_content_keys
method now raises the new CEKNotFound
and EmptyLicense
exceptions not
ValueError
exceptions.sys.exit(1)
. Callees do not need to make any
changes. The exception should continue to go up the call stack and get handled by the dl
command.