View Full Version : BestSource (BS)
Myrsloik
17th July 2022, 17:35
The time has finally come for a universal source filter that doesn't suck. FFMS2 was good back when only B-frames roamed the earth but now we have "super totally keyframes (IDR)", "referenced but hidden frames (VPx)" and "just doesn't work because FFmpeg internals changed frames". Insanity!
BestSource solves all of these issues by only performing linear decoding. Plus some tricks with multiple decoder instances and a large cache to hide some of the potentially slow seeking. Throwing more hardware at a problem does help. Especially if you have 16 cores.
Indexing files to get exact sample and frame counts is enabled by default but can be turned off by settings exact=False to speed up file opening. All indexing information is also stored in a single json file to not gunk up your pristine filesystems.
Indexless mode generally seems to works fairly well for avi and mp4 files. Do however note that nvops are dropped so some avi files will turn into VFR.
64 bit and VapourSynth only. BestAudioSource is now discontinued.
Usage:
core.bs.VideoSource(source="meh.mkv")
core.bs.AudioSource(source="meh.mkv")
kedautinh12
17th July 2022, 17:44
Can it's support avs too??
mastrboy
17th July 2022, 22:44
Very interesting, not very often we get new source filters to play with.
Have you done any scale testing with a large json file? If you plan to store every file's index in the same file it will grow pretty quick. (And json parsing is more CPU expensive than one would expect)
How many movies can be indexed before the json file gets so big it starts to have adverse effects on opening the file?
Myrsloik
18th July 2022, 10:13
Very interesting, not very often we get new source filters to play with.
Have you done any scale testing with a large json file? If you plan to store every file's index in the same file it will grow pretty quick. (And json parsing is more CPU expensive than one would expect)
How many movies can be indexed before the json file gets so big it starts to have adverse effects on opening the file?
Have you done any scale testing with a large json file? <- nope
If you plan to store every file's index in the same file it will grow pretty quick. <- the "index" data is only ~300 bytes for a file where most of it is the filename
How many movies can be indexed before the json file gets so big it starts to have adverse effects on opening the file? <- 100k+?
You can also set a custom cache path to split it into smaller chunks if you ever encounter this problem
mastrboy
18th July 2022, 13:52
Have you done any scale testing with a large json file? <- nope
If you plan to store every file's index in the same file it will grow pretty quick. <- the "index" data is only ~300 bytes for a file where most of it is the filename
How many movies can be indexed before the json file gets so big it starts to have adverse effects on opening the file? <- 100k+?
You can also set a custom cache path to split it into smaller chunks if you ever encounter this problem
Compared to the index created by LWLibavVideoSource, BestSource sounds a lot more efficient, I just indexed a 1:45hour long movie to check and .LWI index file ended up using 13,2 megabytes.
And by having the functionality to specificy custom paths should indeed be a good solution if the file ends up too big.
I guess my concerns about the filesize where wrong...
mastrboy
18th July 2022, 16:32
Did some quick benchmarks on decoding speed and indexing speed.
Seems to be on par with core.ffms2.Source for decoding speed, but a lot slower than both ffms2 and lsmas for indexing
Decode speed test:
output = core.ffms2.Source(source=rf"00014.m2ts")
output.set_output(0)
Script evaluation done in 0.16 seconds
Output 10001 frames in 25.63 seconds (390.17 fps)
output = core.lsmas.LWLibavSource(source=rf"00014.m2ts")
output.set_output(0)
Script evaluation done in 0.19 seconds
Output 10001 frames in 19.46 seconds (513.80 fps)
output = core.bs.VideoSource(source=rf"00014.m2ts")
output.set_output(0)
[matroska,webm @ 000002D34F33BF40] Unsupported encoding typeUnsupported encoding typeCould not find codec parameters for stream 5 (Subtitle: hdmv_pgs_subtitle (pgssub)): unspecified size
Consider increasing the value for the 'analyzeduration' (0) and 'probesize' (5000000) options
[matroska,webm @ 000002D34F33BF40] Could not find codec parameters for stream 6 (Subtitle: hdmv_pgs_subtitle (pgssub)): unspecified size
Consider increasing the value for the 'analyzeduration' (0) and 'probesize' (5000000) options
Script evaluation done in 0.09 seconds
Output 10001 frames in 25.49 seconds (392.37 fps)
Index speed test (Powershell to measure time):
core.ffms2.Source(source=rf"00014.m2ts")
Measure-Command { vspipe -e 1 -p .\test.vpy . }
TotalSeconds : 3,2294295
core.lsmas.LWLibavSource(source=rf"00014.m2ts")
Measure-Command { vspipe -e 1 -p .\test.vpy . }
TotalSeconds : 3,809994
core.bs.VideoSource(source=rf"00014.m2ts")
Measure-Command { vspipe -e 1 -p .\test.vpy . }
TotalSeconds : 86,2428886
Hardware: AMD 3900x, 32GB 3200 Ram, Samsung EVO970 NVME. (Windows10)
The "cachepath" parameter doesn't write a file, it seems to go trough the process of creating a index, but I never get a file written.
I tried with and without full path. (cachepath="c:/test/indexfile.json" | cachepath="indexfile.json")
lansing
18th July 2022, 16:42
Tested with my blu-ray m2ts file, 24 minutes video, my machine is a 5900x.
BestSource took 1:12 to index with all threads running at about 50%, seeking forward or backward took over 10+ seconds.
ffms2 took 5 seconds to index and seeking is instant.
Myrsloik
18th July 2022, 17:47
...
The "cachepath" parameter doesn't write a file, it seems to go trough the process of creating a index, but I never get a file written.
I tried with and without full path. (cachepath="c:/test/indexfile.json" | cachepath="indexfile.json")
It's a path. So you should specify something like c:\test\ and then bsindex.json will be read/written from there.
Getting an exact frame count is slower than FFMS2 because every frame is decoded and not just parsed (possibly incorrectly).
Obviously seeking is slower with linear decoding only. What did you expect? It's more or less BestAudioSource's idea applied to video as well.
I wasn't kidding when I said that this is the solution is based on throwing lots of hardware at a problem. This would have been complete insanity without the cheap 16 core CPUs we now have.
ChaosKing
18th July 2022, 18:14
I guess you work with ffms2/lsmas but switch to BS™ for the encode :devil:
mastrboy
18th July 2022, 18:30
It's a path. So you should specify something like c:\test\ and then bsindex.json will be read/written from there.
Works fine when just specifying directory, I assumed I could specify full filename as most Path options in Windows usually is the full path and usually Directory or Folder is used as terms instead...
Maybe throw an error if it fails to write a index file, rather than silently continue could further prevent this confusion.
Yomiko
19th July 2022, 01:03
I guess you work with ffms2/lsmas but switch to BS™ for the encode :devil:
What's going to be the benefit?
ChaosKing
19th July 2022, 08:55
Faster seeking times while you work on your script and accurate seeking while encoding (temporal filters will thank you!)
Does it have av1 support? ( I have a RTX 3070Ti + Ryzen 3600. As far as I know the GPU does support hardware accelerated AV1 decoding)
Video: rav1e_b_4600.ivf
-----------------------------------
[av1 @ 000001931E36A8C0] Your platform doesn't suppport hardware accelerated AV1 decoding.
[av1 @ 000001931E36A8C0] Failed to get pixel format.
[av1 @ 000001931E36A8C0] Missing Sequence Header.
...
[av1 @ 000001931EAED980] get_buffer() failed
[av1 @ 000001931EAED980] thread_get_buffer() failed
[av1 @ 000001931EAED980] Failed to allocate space for current frame.
[av1 @ 000001931EAED980] Get current frame error
[av1 @ 000001931EAED980] Failed to get reference frame.
[av1 @ 000001931EAED980] video_get_buffer: image parameters invalid
[av1 @ 000001931EAED980] get_buffer() failed
[av1 @ 000001931EAED980] thread_get_buffer() failed
[av1 @ 000001931EAED980] Failed to allocate space for current frame.
[av1 @ 000001931EAED980] Get current frame error
[av1 @ 000001931EAED980] Failed to get reference frame.
[av1 @ 000001931EAED980] video_get_buffer: image parameters invalid
[av1 @ 000001931EAED980] get_buffer() failed
[av1 @ 000001931EAED980] thread_get_buffer() failed
[av1 @ 000001931EAED980] Failed to allocate space for current frame.
[av1 @ 000001931EAED980] Get current frame error
[av1 @ 000001931EAED980] Failed to get reference frame.
[av1 @ 000001931EAED980] video_get_buffer: image parameters invalid
[av1 @ 000001931EAED980] get_buffer() failed
[av1 @ 000001931EAED980] thread_get_buffer() failed
[av1 @ 000001931EAED980] Failed to allocate space for current frame.
It could be the new king of accurate frame seeking.
Seeking test chart:
https://i.imgur.com/VSp4gl5.png
Myrsloik
19th July 2022, 10:55
Faster seeking times while you work on your script and accurate seeking while encoding (temporal filters will thank you!)
Does it have av1 support? ( I have a RTX 3070Ti + Ryzen 3600. As far as I know the GPU does support hardware accelerated AV1 decoding)
...
It could be the new king of accurate frame seeking.
Seeking test chart:
https://i.imgur.com/VSp4gl5.png
I didn't compile it with any av1 decoder so probably not. Will add it in the next test build.
Maybe I should take a look at GPU decoding too...
Myrsloik
19th July 2022, 13:57
Test 6: Now compiled with libdav1d and the cache path now is actually the full path to the file to cache things in. Link in first post.
jlw_4049
19th July 2022, 14:03
Is there anyway to keep indexing time to move a little quicker?
Myrsloik
19th July 2022, 14:25
Is there anyway to keep indexing time to move a little quicker?
That would be FFMS2 you're talking about.
jlw_4049
19th July 2022, 16:04
That would be FFMS2 you're talking about.
What benefits would you get using BS over FFMS2?
Rumbah
19th July 2022, 17:46
For me it works like intended.
Simple 1080p H264 decoding is about 8% slower than LsmashSource with indexing prior to the decoding test (1080fps vs 990fps).
For my use case I'll stay with Lsmash as I use Vapoursynth to split videos in 8 equal parts and encode them in parallel. This is much slower with BS as it has to decode much more. For my use it was about a factor of 7-8.
Myrsloik
19th July 2022, 21:17
GPU decoding added. Simply add hwdevice="cuda" or "d3d11va" to activate. Updated link in the first post.
Rumbah
26th July 2022, 01:01
I did some testing. File was a 10 Mbit/s h264 file, 1920x960 , 45mins.
Hardware is a 12 core/24 threads Ryzen 3900X, Nvidia 3060 Ti, Windows 10.
Indexing speed:
LSmash : 2s
BS_CPU : 69s (about 50% CPU usage)
BS_GPU_DX11 : 252s (about 0% CPU usage, 75% GPU usage)
BS_GPU_Cuda : Error ([h264 @ 000001E1CF0A8200] No decoder surfaces left) the numbers change till you close the process
Full decoding of the file without indexing:
LSmash : 64s
BS_CPU : 72s (about 50% CPU usage)
BS_GPU_DX11 : 117s (about 5% CPU usage, 75% GPU usage)
BS_GPU_Cuda : Error ([h264 @ 000001E1CF0A8200] No decoder surfaces left)
So for me Cuda does not work at all, it just throws the error above.
Full CPU decoding is still a little bit slower than LSmash Libav.
GPU indexing takes pretty long but does not use CPU ressources.
GPU decoding only is much faster than GPU indexing.
GPU decoding uses one full CPU core so the decoding there might be CPU bound.
Myrsloik
26th July 2022, 09:55
The CPU decoding speed is determined by how FFmpeg was compiled and isn't that interesting. Make a -O99 gcc compile if you care. I tend to prefer easy to develop for workflows...
Now for the interesting observations:
Somehow your linear decoding with DX11 is faster than indexing. Indexing should be faster or the same since it's doing the same thing more or less (just without reading back decoded frames).
Cuda doesn't seem to work properly for anyone. Some people get as far as to get decoded frames with mild corruption. Probably some kind of FFmpeg bug. Maybe it works better outside windows.
ChaosKing
26th July 2022, 11:26
Cuda decoding for vob files seems to work
My quick test (version 7)
Ryzen 3600 OC, GPU 3070 TI
cpu: 1200fps
cuda: 780 fps
dx11: 710 fps
EDIT
CUDA h264 BD works, but sometimes a green frame is shown
h264 10 works too
Rumbah
26th July 2022, 12:06
The CPU decoding speed is determined by how FFmpeg was compiled and isn't that interesting. Make a -O99 gcc compile if you care. I tend to prefer easy to develop for workflows...
No worries, I was just curious.
Now for the interesting observations:
Somehow your linear decoding with DX11 is faster than indexing. Indexing should be faster or the same since it's doing the same thing more or less (just without reading back decoded frames).
Ok, tested some more with different files and got the following results:
33 min 5 Mbit/s h264 1080p
Indexing
Software : 42s (50% CPU)
DX11 : 187s (0% CPU, 75% GPU) Video Decode
CUDA : crash
Decoding
Software : 45s (50% CPU)
DX11 : 97s (0% CPU, 75% GPU) Video Decode
CUDA : crash
33 min 15 Mbit/s h265 2160p
Indexing
Software : 269s (50% CPU)
DX11 : 111s (1.8% CPU, 98% GPU) Video Decode
CUDA : 105s (1.1% CPU, 100% GPU) Video Decode
Decoding
Software : 340s (50% CPU)
DX11 : 977s (4.8% CPU, 42% GPU) 3D
CUDA : 770s (4.3% CPU, 50% GPU) Video Decode
So h264 Cuda still crashes for me and that indexing is slower than decoding seems reproducible for me.
For the 4k hevc decoding Cuda works and is faster than DX11.
But hardware decoding is much slower than indexing. For DX11 Decoding the Windows task manager shows 3D instead of video decode. For Cuda it shows video decode but it still only uses 50% GPU and is much slower than indexing.
The indexing tests were done with "vspipe --info file.vpy", the decoding tests with "vspipe file.vpy ." and a pre existing index.
Myrsloik
26th July 2022, 15:15
Reading back frames is really slow according to your tests. I'm not surprised. Don't expect big performance improvements until someone makes things more threaded and have prefetch for GPU decoding. Probably won't be done by me anytime soon.
A speed comparison with DGDecNV would be very interesting if you have time to do it.
Rumbah
26th July 2022, 17:18
Sure thing. Same as before, just added the DGDecodeNV results.
One thing I noted is that LSmash and BSSource return a 10bit video for the HEVC file (it is a 10bit file) while DGDecode returns 16bit.
33 min 5 Mbit/s h264 1080p
Decoding
Software : 45s (50% CPU)
DX11 : 97s (0% CPU, 75% GPU) Video Decode
CUDA : crash
DGDecodeNV : 60s (5% CPU, 100% GPU) Video Decode
33 min 15 Mbit/s h265 2160p
Decoding
Software : 340s (50% CPU)
DX11 : 977s (4.8% CPU, 42% GPU) 3D
CUDA : 770s (4.3% CPU, 50% GPU) Video Decode
DGDecodeNV : 307s (4.9% CPU, 67% GPU) Video Decode
_Al_
26th July 2022, 23:35
I guess you work with ffms2/lsmas but switch to BS™ for the encode :devil:
to not forget to actually switch those source plugins, this could be used:
import vapoursynth as vs
from vapoursynth import core
source = r"meh.mkv"
if __name__ == '__vapoursynth__':
my_vnode = core.bs.VideoSource(source)
else:
my_vnode = core.ffms2.Source(source)
.
.
.
Yomiko
27th July 2022, 04:35
unfortunately you will have __vapoursynth__ in previewers as well
ChaosKing
27th July 2022, 09:31
I would simply pass an arg parameter to vspipe and check for that instead of __vapoursynth__
http://www.vapoursynth.com/doc/output.html#options
_Al_
29th July 2022, 20:05
Does vsedit also changes __main__ to "__vapoursynth__"? Why? I thought this is done by vspipe only and the way preview is done, is, to get a video node using by vs.get_output() or vs.get_outputs() then when requesting a frame, changing it to RGB an putting on screen.
ok, just tested it with some very old version of vsedit but __main__ is not even defined when trying to preview script, perhaps because of using .vpy, not .py, to evaluate script, not sure. If using a python previewer with .py script, that __main__ checking for "__vapoursynth__" is fine.
Yomiko
30th July 2022, 00:19
It's a feature of vsscript, not vsedit or vspipe.
tebasuna51
8th July 2023, 13:16
Please support AviSynth+ r4001 (https://forum.doom9.org/showthread.php?p=1989323#post1989323) including the audio channel mask.
Myrsloik
3rd March 2024, 22:24
R1 RC2 (https://github.com/vapoursynth/bestsource/releases/tag/R1-RC2) is out. Help with the testing so there can finally be a proper release.
Guest
31st May 2024, 08:15
Is it possible to change this script to use BS instead of LSmash / LWLibavAudioSource :-
#AudioSource
LoadPlugin("C:\RipBot264\Tools\AviSynth plugins\lsmash\LSMASHSource.dll")
audio=LWLibavAudioSource("H:DV edits\Season 3\faded audio & subs\S03 E04 vol 3.0 fade.eac3",cachefile="E:\Temp\RipBot264temp\job3\S03 E04 vol 3.0 fade.eac3.lwi").ConvertAudioToFloat.ResampleAudio(48000)
my test, didn't work :-
#AudioSource
LoadPlugin("C:\RipBot264\Tools\AviSynth plugins\BestSource-R4-x64\BestSource.dll")
audio=BSAudioSource("H:DV edits\Season 3\faded audio & subs\S03 E04 vol 3.0 fade.eac3",cachefile="E:\Temp\RipBot264temp\job3\S03 E04 vol 3.0 fade.eac3.lwi").ConvertAudioToFloat.ResampleAudio(48000)
Emulgator
31st May 2024, 08:39
Drop the cachefile.
.lwi belongs to LWLibav.
Guest
31st May 2024, 08:50
Drop the cachefile.
.lwi belongs to LWLibav.
Interesting to get a reply from you, as you commented on my questions about this on the RipBot264 thread :)
So something like this :-
#AudioSource
LoadPlugin("C:\RipBot264\Tools\AviSynth plugins\BestSource-R4-x64\BestSource.dll")
audio=BSAudioSource("H:DV edits\Season 3\faded audio & subs\S03 E04 vol 3.0 fade.eac3").ConvertAudioToFloat.ResampleAudio(48000)
tebasuna51
31st May 2024, 21:19
So something like this :-
#AudioSource
LoadPlugin("C:\RipBot264\Tools\AviSynth plugins\BestSource-R4-x64\BestSource.dll")
audio=BSAudioSource("H:DV edits\Season 3\faded audio & subs\S03 E04 vol 3.0 fade.eac3").ConvertAudioToFloat.ResampleAudio(48000)
Yes.
BTW ConvertAudioToFloat do nothing, because the decoded audio from lossy formats is always float.
Guest
1st June 2024, 04:27
Yes.
BTW ConvertAudioToFloat do nothing, because the decoded audio from lossy formats is always float.
Thanks again, teb...
But leaving the ResampleAudio(48000) would be recommended, just in case the audio track is lower.
Guest
1st June 2024, 04:29
Drop the cachefile.
.lwi belongs to LWLibav.
:thanks:, that worked, it was easier than I thought it was going to be, just a quick edit to the generated scripts, and you're away. :)
Myrsloik
14th July 2024, 18:04
Time for a bump. R6 is out now and fixes a lot of problems with CFR mode.
tebasuna51
15th July 2024, 08:21
Thanks Myrsloik, I found it at https://github.com/vapoursynth/bestsource/releases
In first post I read: "Full release is on github now so remove test versions"
Maybe you can add the link to found the last version.
Also you say: "64 bit and VapourSynth only."
But work fine in AviSynth+ (thanks)
Kurt.noise
17th August 2024, 11:16
Hi,
Time for a bump. R6 is out now and fixes a lot of problems with CFR mode.
Tested R6 within Avisynth+ 3.7.3 on Windows 11 , using this avs script :
LoadPlugin("E:\tools\bestsource\BestSource.dll")
BSVideoSource("E:\Video\HEVC.mp4",HWDevice=d3d11va)
I get an error playing the script through mpc-hc :
https://iili.io/dGNKzcx.md.png (https://freeimage.host/i/dGNKzcx)
Same issue replacing d3d11va by dxva2 or vulkan hardware device type.
And also same error playing the script through ffmpeg executable...
Without hwdevice argument, that works, of course, as expected.
And using such hardware decoding directly through FFmpeg, that works also correctly :
https://iili.io/dGN5O8P.md.png (https://freeimage.host/i/dGN5O8P)
Any idea ?
Kurt.noise
17th August 2024, 12:16
Erff, I missed the quotation mark since its a string :D
LoadPlugin("E:\tools\bestsource\BestSource.dll")
BSVideoSource("E:\Video\HEVC.mp4",HWDevice="d3d11va")
Sorry for the noise...vulkan is still not supported yet, right ?
Myrsloik
17th August 2024, 15:59
Erff, I missed the quotation mark since its a string :D
LoadPlugin("E:\tools\bestsource\BestSource.dll")
BSVideoSource("E:\Video\HEVC.mp4",HWDevice="d3d11va")
Sorry for the noise...vulkan is still not supported yet, right ?
I actually haven't tested it. It's also possible the release wasn't compiled with support enabled. Will investigate before next release
amayra
20th September 2024, 07:10
out of curiosity why is there no GStreamer plugin for VapourSynth ?
I had a horrible FFmpeg experience back when I used to use Windows 7 before I moved to Linux
isidroco
17th March 2025, 23:33
Does BestSource work on Avisynth 64 non plus version?
Myrsloik
18th March 2025, 16:13
Does BestSource work on Avisynth 64 non plus version?
Probably not? Not tested at least.
Myrsloik
18th March 2025, 16:18
R11 is out. It fixes the framerate guessing problems reported earlier in the thread.
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.