View Full Version : libass in VapourSynth
jay123210599
1st November 2025, 21:41
How do I get VapourSynth scripts to use libass to render subtitles?
Selur
1st November 2025, 22:41
https://github.com/vapoursynth/subtext is based on libass and works fine here:
# Imports
import vapoursynth as vs
# getting Vapoursynth core
import sys
import os
core = vs.core
# Limit frame cache to 48473MB
core.max_cache_size = 48473
# Import scripts folder
scriptPath = 'F:/Hybrid/64bit/vsscripts'
sys.path.insert(0, os.path.abspath(scriptPath))
# loading plugins
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/SubtitleFilter/SubText/SubText.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/SourceFilter/BestSource/BestSource.dll")
# Import scripts
import validate
# Source: 'G:\TestClips&Co\files\Subtitles\dummy.mkv'
# Current color space: YUV420P10, bit depth: 10, resolution: 1280x720, frame rate: 23.976fps, scanorder: progressive, yuv luminance scale: limited, matrix: 709, format: AVC
# Loading G:\TestClips&Co\files\Subtitles\dummy.mkv using BestSource)
clip = core.bs.VideoSource(source="G:/TestClips&Co/files/Subtitles/dummy.mkv", cachepath="J:/tmp/dummy_bestSource", track=0, hwdevice="opencl")
frame = clip.get_frame(0)
# setting color matrix to 709.
clip = core.std.SetFrameProps(clip, _Matrix=vs.MATRIX_BT709)
# setting color transfer (vs.TRANSFER_BT709), if it is not set.
if validate.transferIsInvalid(clip):
clip = core.std.SetFrameProps(clip=clip, _Transfer=vs.TRANSFER_BT709)
# setting color primaries info (to vs.PRIMARIES_BT709), if it is not set.
if validate.primariesIsInvalid(clip):
clip = core.std.SetFrameProps(clip=clip, _Primaries=vs.PRIMARIES_BT709)
# setting color range to TV (limited) range.
clip = core.std.SetFrameProps(clip=clip, _ColorRange=vs.RANGE_LIMITED)
# making sure frame rate is set to 23.976fps
clip = core.std.AssumeFPS(clip=clip, fpsnum=24000, fpsden=1001)
# making sure the detected scan type is set (detected: progressive)
clip = core.std.SetFrameProps(clip=clip, _FieldBased=vs.FIELD_PROGRESSIVE) # progressive
# Loading G:\Output\dummy_id_2_lang_und_default.ass using SubText
clip = core.sub.TextFile(clip, file="G:/Output/dummy_id_2_lang_und_default.ass", fontdir="F:/Hybrid/settings/fonts")
# set output frame rate to 23.976fps (progressive)
clip = core.std.AssumeFPS(clip=clip, fpsnum=24000, fpsden=1001)
# output
clip.set_output()
There is also AssRender https://github.com/AmusementClub/assrender, which is also based on libass and works fine too:
# Imports
import vapoursynth as vs
# getting Vapoursynth core
import sys
import os
core = vs.core
# Limit frame cache to 48473MB
core.max_cache_size = 48473
# Import scripts folder
scriptPath = 'F:/Hybrid/64bit/vsscripts'
sys.path.insert(0, os.path.abspath(scriptPath))
# loading plugins
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/SubtitleFilter/AssRenderer/assrender.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/SourceFilter/BestSource/BestSource.dll")
# Import scripts
import validate
# Source: 'G:\TestClips&Co\files\Subtitles\dummy.mkv'
# Current color space: YUV420P10, bit depth: 10, resolution: 1280x720, frame rate: 23.976fps, scanorder: progressive, yuv luminance scale: limited, matrix: 709, format: AVC
# Loading G:\TestClips&Co\files\Subtitles\dummy.mkv using BestSource)
clip = core.bs.VideoSource(source="G:/TestClips&Co/files/Subtitles/dummy.mkv", cachepath="J:/tmp/dummy_bestSource", track=0, hwdevice="opencl")
frame = clip.get_frame(0)
# setting color matrix to 709.
clip = core.std.SetFrameProps(clip, _Matrix=vs.MATRIX_BT709)
# setting color transfer (vs.TRANSFER_BT709), if it is not set.
if validate.transferIsInvalid(clip):
clip = core.std.SetFrameProps(clip=clip, _Transfer=vs.TRANSFER_BT709)
# setting color primaries info (to vs.PRIMARIES_BT709), if it is not set.
if validate.primariesIsInvalid(clip):
clip = core.std.SetFrameProps(clip=clip, _Primaries=vs.PRIMARIES_BT709)
# setting color range to TV (limited) range.
clip = core.std.SetFrameProps(clip=clip, _ColorRange=vs.RANGE_LIMITED)
# making sure frame rate is set to 23.976fps
clip = core.std.AssumeFPS(clip=clip, fpsnum=24000, fpsden=1001)
# making sure the detected scan type is set (detected: progressive)
clip = core.std.SetFrameProps(clip=clip, _FieldBased=vs.FIELD_PROGRESSIVE) # progressive
# Loading G:\Output\dummy_id_2_lang_und_default.ass using AssRender
clip = core.assrender.TextSub(clip, file="G:/Output/dummy_id_2_lang_und_default.ass", fontdir="F:/Hybrid/settings/fonts")
# set output frame rate to 23.976fps (progressive)
clip = core.std.AssumeFPS(clip=clip, fpsnum=24000, fpsden=1001)
# output
clip.set_output()
Cu Selur
jay123210599
2nd November 2025, 02:27
https://github.com/vapoursynth/subtext is based on libass and works fine here:
# Imports
import vapoursynth as vs
# getting Vapoursynth core
import sys
import os
core = vs.core
# Limit frame cache to 48473MB
core.max_cache_size = 48473
# Import scripts folder
scriptPath = 'F:/Hybrid/64bit/vsscripts'
sys.path.insert(0, os.path.abspath(scriptPath))
# loading plugins
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/SubtitleFilter/SubText/SubText.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/SourceFilter/BestSource/BestSource.dll")
# Import scripts
import validate
# Source: 'G:\TestClips&Co\files\Subtitles\dummy.mkv'
# Current color space: YUV420P10, bit depth: 10, resolution: 1280x720, frame rate: 23.976fps, scanorder: progressive, yuv luminance scale: limited, matrix: 709, format: AVC
# Loading G:\TestClips&Co\files\Subtitles\dummy.mkv using BestSource)
clip = core.bs.VideoSource(source="G:/TestClips&Co/files/Subtitles/dummy.mkv", cachepath="J:/tmp/dummy_bestSource", track=0, hwdevice="opencl")
frame = clip.get_frame(0)
# setting color matrix to 709.
clip = core.std.SetFrameProps(clip, _Matrix=vs.MATRIX_BT709)
# setting color transfer (vs.TRANSFER_BT709), if it is not set.
if validate.transferIsInvalid(clip):
clip = core.std.SetFrameProps(clip=clip, _Transfer=vs.TRANSFER_BT709)
# setting color primaries info (to vs.PRIMARIES_BT709), if it is not set.
if validate.primariesIsInvalid(clip):
clip = core.std.SetFrameProps(clip=clip, _Primaries=vs.PRIMARIES_BT709)
# setting color range to TV (limited) range.
clip = core.std.SetFrameProps(clip=clip, _ColorRange=vs.RANGE_LIMITED)
# making sure frame rate is set to 23.976fps
clip = core.std.AssumeFPS(clip=clip, fpsnum=24000, fpsden=1001)
# making sure the detected scan type is set (detected: progressive)
clip = core.std.SetFrameProps(clip=clip, _FieldBased=vs.FIELD_PROGRESSIVE) # progressive
# Loading G:\Output\dummy_id_2_lang_und_default.ass using SubText
clip = core.sub.TextFile(clip, file="G:/Output/dummy_id_2_lang_und_default.ass", fontdir="F:/Hybrid/settings/fonts")
# set output frame rate to 23.976fps (progressive)
clip = core.std.AssumeFPS(clip=clip, fpsnum=24000, fpsden=1001)
# output
clip.set_output()
There is also AssRender https://github.com/AmusementClub/assrender, which is also based on libass and works fine too:
# Imports
import vapoursynth as vs
# getting Vapoursynth core
import sys
import os
core = vs.core
# Limit frame cache to 48473MB
core.max_cache_size = 48473
# Import scripts folder
scriptPath = 'F:/Hybrid/64bit/vsscripts'
sys.path.insert(0, os.path.abspath(scriptPath))
# loading plugins
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/SubtitleFilter/AssRenderer/assrender.dll")
core.std.LoadPlugin(path="F:/Hybrid/64bit/vsfilters/SourceFilter/BestSource/BestSource.dll")
# Import scripts
import validate
# Source: 'G:\TestClips&Co\files\Subtitles\dummy.mkv'
# Current color space: YUV420P10, bit depth: 10, resolution: 1280x720, frame rate: 23.976fps, scanorder: progressive, yuv luminance scale: limited, matrix: 709, format: AVC
# Loading G:\TestClips&Co\files\Subtitles\dummy.mkv using BestSource)
clip = core.bs.VideoSource(source="G:/TestClips&Co/files/Subtitles/dummy.mkv", cachepath="J:/tmp/dummy_bestSource", track=0, hwdevice="opencl")
frame = clip.get_frame(0)
# setting color matrix to 709.
clip = core.std.SetFrameProps(clip, _Matrix=vs.MATRIX_BT709)
# setting color transfer (vs.TRANSFER_BT709), if it is not set.
if validate.transferIsInvalid(clip):
clip = core.std.SetFrameProps(clip=clip, _Transfer=vs.TRANSFER_BT709)
# setting color primaries info (to vs.PRIMARIES_BT709), if it is not set.
if validate.primariesIsInvalid(clip):
clip = core.std.SetFrameProps(clip=clip, _Primaries=vs.PRIMARIES_BT709)
# setting color range to TV (limited) range.
clip = core.std.SetFrameProps(clip=clip, _ColorRange=vs.RANGE_LIMITED)
# making sure frame rate is set to 23.976fps
clip = core.std.AssumeFPS(clip=clip, fpsnum=24000, fpsden=1001)
# making sure the detected scan type is set (detected: progressive)
clip = core.std.SetFrameProps(clip=clip, _FieldBased=vs.FIELD_PROGRESSIVE) # progressive
# Loading G:\Output\dummy_id_2_lang_und_default.ass using AssRender
clip = core.assrender.TextSub(clip, file="G:/Output/dummy_id_2_lang_und_default.ass", fontdir="F:/Hybrid/settings/fonts")
# set output frame rate to 23.976fps (progressive)
clip = core.std.AssumeFPS(clip=clip, fpsnum=24000, fpsden=1001)
# output
clip.set_output()
Cu Selur
Could you make the script shorter, please? Only included what is needed.
Selur
2nd November 2025, 07:57
Assuming the filter is autoloaded and the used fonts can automatically be found by the filter:
clip = core.assrender.TextSub(clip, file="< Path to ass file>")
read https://github.com/AmusementClub/assrender/blob/master/README.md for call details
and
clip = core.sub.TextFile(clip, file="< Path to ass file>")
read https://github.com/vapoursynth/subtext/blob/master/docs/subtext.rst for call details.
should work.
Cu Selur
jay123210599
2nd November 2025, 14:46
Assuming the filter is autoloaded and the used fonts can automatically be found by the filter:
clip = core.assrender.TextSub(clip, file="< Path to ass file>")
read https://github.com/AmusementClub/assrender/blob/master/README.md for call details
and
clip = core.sub.TextFile(clip, file="< Path to ass file>")
read https://github.com/vapoursynth/subtext/blob/master/docs/subtext.rst for call details.
should work.
Cu Selur
How do I add multiple font attachments using these plugins? I want my subtitles to use those fonts and NOT the system ones.
Selur
2nd November 2025, 16:03
In my first example I pointed the filter to a directory with the needed fonts you can do the same.
You really might want to read the infos about the call details I linked top,...
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.