"begin" option doesn't affect when the video starts
joek13 opened this issue · 10 comments
As the title says, when invoking ytdl, the begin option doesn't actually affect where the video starts to download.
An example:
const ytdl = require("ytdl-core");
const fs = require("fs");
ytdl("https://www.youtube.com/watch?v=q6EoRBvdVPQ", {begin: "5s"}).pipe(fs.createWriteStream("out.mp4"));
The resulting downloaded video starts at the very beginning, regardless of the value of "begin."
I tested this with a longer video. And for some odd reason, when I try the begin
option with 5s
or anything below that, the video starts at 0. But with 6s
or anything above that, it downloads starting at the requested time.
I'm going to guess that this is some YouTube limitation where it won't let you request the download if the time is too close to the start of the video, or the video is too short.
I tested this with a longer video. And for some odd reason, when I try the begin option with 5s or anything below that, the video starts at 0. But with 6s or anything above that, it downloads starting at the requested time.
I'm going to guess that this is some YouTube limitation where it won't let you request the download if the time is too close to the start of the video, or the video is too short.
I tested what you're saying here and saw similar results -- longer videos didn't ignore the "begin" option. Maybe this should be noted in the docs, just as a warning?
I also was having some issues with the begin option not working correctly, but then I saw this issue was closed. However, I found something interesting.
In the original video that @joek13 uses in the example, if you use the begin option at 6s, the video starts at the beginning. But with this similar video of identical length (https://www.youtube.com/watch?v=0tjUqKNf7gU), using the begin option at 6s works exactly as intended. The only difference between the two videos as far as I could tell was the quality, the former being 360p and the latter being 1080p.
I did some further testing and found that the begin option consistently did not work with any videos 480p quality and below, even taking into consideration the "five second rule" thing. So I think the length of the video doesn't actually matter if it's longer than 5s, but the quality does in terms of whether the begin options works or not.
Is there anything obvious that I might be missing to cause this to not work, or is this an actual new bug?
That's really weird. I wish things were more consistent with YouTube.
Any update on this ?
I am using filter 'audioonly' and I couldn't find a video wich works with begin parameter.
With only "highest" quality it works (at least for the video I tested).
As above states, it looks like it won't work with any video 480p or below. I also tried using it with a super long video that's in 1080p, and it also wouldn't work with audioonly
.
There's not much that can be done, except.... post-processing with something like ffmpeg. But even so, the whole file including the non-wanted starting section would have to be downloaded.
There's not much that can be done, except.... post-processing with something like ffmpeg. But even so, the whole file including the non-wanted starting section would have to be downloaded.
Yes that's what I was trying to avoid ...
Couldn't it be possible to use range option to download from a start point and use ffmpeg convert it ?
I already use ffmpeg to convert to 16bit PCM so ... I tried to feed the stream to ffmpeg but it keep failing because it cannot recognize input format I guess. But I don't see how to specify it.. Any clue ?
Otherwise with ffmpeg we can specify seekInput but that implies downloading the file from the beginning.
Couldn't it be possible to use range option to download from a start point and use ffmpeg convert it ?
I already use ffmpeg to convert to 16bit PCM so ... I tried to feed the stream to ffmpeg but it keep failing because it cannot recognize input format I guess. But I don't see how to specify it.. Any clue ?
The range
options specifies byte range. Often, the received file won't have their metadata since that is usually specified in the beginning. And ffmpeg will have a hard time guessing what the file is.
It's also difficult to guess the byte range based on a given time.
The range options specifies byte range. Often, the received file won't have their metadata since that is usually specified in the beginning. And ffmpeg will have a hard time guessing what the file is.
That's what I want: give ffmpeg a hint on the format .. but I can't figure out any option of ffmpeg that does that. The other solution here is to download metadata and then only starts at the given range. Writing them to the stream should hint ffmpeg. I'll try investigate that ..
It's also difficult to guess the byte range based on a given time.
If we know the format we should be able to calculate the byte position of a given time.
Okay downloading the beginning and then jump at a given time works (if we have the offset corresponding to the given time). For example, for itag 251
(opus audio only, bitrate 160) I have to download bytes 0-x
(depending on the video) and after that I can directly jump at the wanted location.
The header length depends on the itag so I guess the simpler will be to map header lengths into format metas.
But you were right, I find it very hard to calculate the offset of a given time .. HTML5 media element does that, and chromium uses ffmpeg (https://www.chromium.org/developers/design-documents/video) ...
Maybe you have an idea on how to get this offset ?
For now I am using fluent-ffmpeg
's .seekInput() method, but downloading the whole file becomes a problem with long video (and we need to seek only in long video ..)
EDIT: I found a way to predict time -> range, is that okay if I create a PR ?