Video Source File Path from .txt file

khaver

Member
There may be a slight delay because of the way I had to implement the skip function. The video file is loaded and starts playing from the beginning for a fraction of a second, then skips to the time indicated in the text file. I don't know if it can be made with precision accuracy.
 

khaver

Member
It would be nice if OBS added a "Cue" setting in the media source properties that would immediately start playback from the cue time instead of from the beginning.
 

onairmitflo

Member
There may be a slight delay because of the way I had to implement the skip function. The video file is loaded and starts playing from the beginning for a fraction of a second, then skips to the time indicated in the text file. I don't know if it can be made with precision accuracy.
If it would stay at an even delay, this would be no problem as a filter to work with the render delay and compensate this. But somehow this delay gets bigger and bigger and balancing it out becomes a bit difficult.
 

onairmitflo

Member
It would be nice if OBS added a "Cue" setting in the media source properties that would immediately start playback from the cue time instead of from the beginning.
In any case... Do you think there is a way to make this more precise with a browser source? So the start time?
 

khaver

Member
I don't know how to add a video file to a browser source. Do you? If you know, can you show what the properties of the browser source would look like? Maybe in the browser source there is a way to start the video playback at a certain time.
 

onairmitflo

Member
If you add a browser source, they must check the "Local files" box, otherwise it won't work at all. I was able to hide the browser icons in previous answers.

14.02_Zd55w223Bx.png


The video is even put in the browser source, but does not jump ahead
 

khaver

Member
New version that uses browser sources. Copy and paste to new MediaFromTXT3.lua file. Remove MediaFromTXT2.lua from OBS scripts.

Lua:
-- Version 3.0
o = obslua

--Set interval in ms to how often the text file is checked for changes. Default = 1000 ms (1 second).
interval = 1000

TEXTFILE= nil
VIDFILE= nil
PVIDFILE= nil
VIDPATH= nil
SKIP = nil
source_name = nil
SCENEAB = {}
SOURCEAB = {}
togg = 1

enabled = true

function toggle(x)
local xx = x - 1
    return (1 - xx) + 1
end

function read_txt_file(filename)
  filename = filename or ''
  local line
  PVIDFILE = VIDFILE
  if not file_exists(filename) then return end
  for line in io.lines(filename) do
  if line ~= "" then
    VIDFILE = line
    local p, t = line:match("^([^=]+)%;(.+)$")
    if p then
        VIDPATH = p
        if not t then t = "0" end
        local tsecond = t:gsub('%.', '')
        local ssecond = tsecond:gsub(',', '%.')
        SKIP = ssecond --SKIP = milli
    end
  end
  end
end

function file_exists(file)
    local f = io.open(file, "rb")
    if f then f:close() end
    return f ~= nil
end

function script_description()
    return [[Reads the path of a video file from a selected text file and updates a selected browser source using the new video file path. It reads the text file for changes at preditermined intervals.]]
end

function script_load()

end

function script_unload()

end

function refresh_media()
    local source = o.obs_get_source_by_name(SOURCEAB[togg])
    if source == nil then return end
    local settings = o.obs_data_create()
    local URL = "file:///" .. VIDPATH .. "#t=" .. SKIP
    print(URL)
    o.obs_data_set_string(settings, "url", URL)
    o.obs_source_update(source, settings)
    o.obs_data_release(settings)
    o.obs_source_release(source)
    cue_media()

end

function cue_media()
    local targetscene = o.obs_get_source_by_name(SCENEAB[togg])
    if targetscene then
        o.obs_frontend_set_current_scene(targetscene)
    end
    o.obs_source_release(targetscene)
    togg = toggle(togg)
end

function timer_callback()
    read_txt_file(TEXTFILE)
    if VIDFILE ~= PVIDFILE then
        refresh_media()
    end
end

function script_properties()
    local p = o.obs_properties_create()

    o.obs_properties_add_bool(p, "enable", "Enable script")
    o.obs_properties_add_path(p, "theTextFile", "mAirList txt File",
        o.OBS_PATH_FILE,
        "Video File List (*.txt)",
        nil
    )

    local sca = o.obs_properties_add_list(p, "scenea", "Scene A", o.OBS_COMBO_TYPE_EDITABLE, o.OBS_COMBO_FORMAT_STRING)
    local objScene
    local sceneitems
    local sceneitem
    local scenes = o.obs_frontend_get_scenes()

    if scenes ~= nil then
        for _, objScene in ipairs(scenes) do
            local scene_source = o.obs_scene_from_source(objScene)
            local scenename = o.obs_source_get_name(objScene)
            o.obs_property_list_add_string(sca, scenename, scenename)
        end
        o.source_list_release(scene_source)
    end
    o.source_list_release(scenes)

    local soa = o.obs_properties_add_list(p, "sourcea", "Scene A Source", o.OBS_COMBO_TYPE_EDITABLE, o.OBS_COMBO_FORMAT_STRING)
    local sources = o.obs_enum_sources()
    if sources ~= nil then
        for _, source in ipairs(sources) do
            source_id = o.obs_source_get_id(source)
            if source_id == "browser_source" then
                local name = o.obs_source_get_name(source)
                o.obs_property_list_add_string(soa, name, name)
            end
        end
    end
    o.source_list_release(sources)

    local scb = o.obs_properties_add_list(p, "sceneb", "Scene B", o.OBS_COMBO_TYPE_EDITABLE, o.OBS_COMBO_FORMAT_STRING)
    local scenes = o.obs_frontend_get_scenes()

    if scenes ~= nil then
        for _, objScene in ipairs(scenes) do
            local scene_source = o.obs_scene_from_source(objScene)
            local scenename = o.obs_source_get_name(objScene)
            o.obs_property_list_add_string(scb, scenename, scenename)
        end
        o.source_list_release(scene_source)
    end
    o.source_list_release(scenes)

    local sob = o.obs_properties_add_list(p, "sourceb", "Scene B Source", o.OBS_COMBO_TYPE_EDITABLE, o.OBS_COMBO_FORMAT_STRING)
    local sources = o.obs_enum_sources()
    if sources ~= nil then
        for _, source in ipairs(sources) do
            local source_id = o.obs_source_get_id(source)
            if source_id == "browser_source" then
                local name = o.obs_source_get_name(source)
                o.obs_property_list_add_string(sob, name, name)
            end
        end
    end
    o.source_list_release(sources)

    return p
end

function script_defaults(s)
    o.obs_data_set_default_bool(s, "enable", false)
end

function script_update(s)
    TEXTFILE = o.obs_data_get_string(s, "theTextFile")
    table.insert(SCENEAB, o.obs_data_get_string(s, "scenea"))
    table.insert(SCENEAB, o.obs_data_get_string(s, "sceneb"))
    table.insert(SOURCEAB, o.obs_data_get_string(s, "sourcea"))
    table.insert(SOURCEAB, o.obs_data_get_string(s, "sourceb"))

    enabled = o.obs_data_get_bool(s, "enable")

    if enabled then
        print("Enabled")
        read_txt_file(TEXTFILE)
        if VIDFILE ~= PVIDFILE then
            refresh_media()
        end
        o.timer_remove(timer_callback)
        o.timer_add(timer_callback, interval)
    else
        print("Disabled")
        o.timer_remove(timer_callback)
    end

end

In Scene A and Scene B, remove or turn off the media sources. Add a browser source to each scene with the following properties (don't worry about filling in the URL path, the script will fill it in).
MediaFromTXT3.jpg


Make sure "Local file" is unchecked.

Add MediaFromTXT3.lua to the OBS scripts. Browse to the mAirList text file. Select the Scene A, Scene A source, Scene B and Scene B source. Check the "Enable script" box. It should start working with instant skipping in the video file.

Let me know how it goes.
 

onairmitflo

Member
New version that uses browser sources. Copy and paste to new MediaFromTXT3.lua file. Remove MediaFromTXT2.lua from OBS scripts.

Lua:
-- Version 3.0
o = obslua

--Set interval in ms to how often the text file is checked for changes. Default = 1000 ms (1 second).
interval = 1000

TEXTFILE= nil
VIDFILE= nil
PVIDFILE= nil
VIDPATH= nil
SKIP = nil
source_name = nil
SCENEAB = {}
SOURCEAB = {}
togg = 1

enabled = true

function toggle(x)
local xx = x - 1
    return (1 - xx) + 1
end

function read_txt_file(filename)
  filename = filename or ''
  local line
  PVIDFILE = VIDFILE
  if not file_exists(filename) then return end
  for line in io.lines(filename) do
  if line ~= "" then
    VIDFILE = line
    local p, t = line:match("^([^=]+)%;(.+)$")
    if p then
        VIDPATH = p
        if not t then t = "0" end
        local tsecond = t:gsub('%.', '')
        local ssecond = tsecond:gsub(',', '%.')
        SKIP = ssecond --SKIP = milli
    end
  end
  end
end

function file_exists(file)
    local f = io.open(file, "rb")
    if f then f:close() end
    return f ~= nil
end

function script_description()
    return [[Reads the path of a video file from a selected text file and updates a selected browser source using the new video file path. It reads the text file for changes at preditermined intervals.]]
end

function script_load()

end

function script_unload()

end

function refresh_media()
    local source = o.obs_get_source_by_name(SOURCEAB[togg])
    if source == nil then return end
    local settings = o.obs_data_create()
    local URL = "file:///" .. VIDPATH .. "#t=" .. SKIP
    print(URL)
    o.obs_data_set_string(settings, "url", URL)
    o.obs_source_update(source, settings)
    o.obs_data_release(settings)
    o.obs_source_release(source)
    cue_media()

end

function cue_media()
    local targetscene = o.obs_get_source_by_name(SCENEAB[togg])
    if targetscene then
        o.obs_frontend_set_current_scene(targetscene)
    end
    o.obs_source_release(targetscene)
    togg = toggle(togg)
end

function timer_callback()
    read_txt_file(TEXTFILE)
    if VIDFILE ~= PVIDFILE then
        refresh_media()
    end
end

function script_properties()
    local p = o.obs_properties_create()

    o.obs_properties_add_bool(p, "enable", "Enable script")
    o.obs_properties_add_path(p, "theTextFile", "mAirList txt File",
        o.OBS_PATH_FILE,
        "Video File List (*.txt)",
        nil
    )

    local sca = o.obs_properties_add_list(p, "scenea", "Scene A", o.OBS_COMBO_TYPE_EDITABLE, o.OBS_COMBO_FORMAT_STRING)
    local objScene
    local sceneitems
    local sceneitem
    local scenes = o.obs_frontend_get_scenes()

    if scenes ~= nil then
        for _, objScene in ipairs(scenes) do
            local scene_source = o.obs_scene_from_source(objScene)
            local scenename = o.obs_source_get_name(objScene)
            o.obs_property_list_add_string(sca, scenename, scenename)
        end
        o.source_list_release(scene_source)
    end
    o.source_list_release(scenes)

    local soa = o.obs_properties_add_list(p, "sourcea", "Scene A Source", o.OBS_COMBO_TYPE_EDITABLE, o.OBS_COMBO_FORMAT_STRING)
    local sources = o.obs_enum_sources()
    if sources ~= nil then
        for _, source in ipairs(sources) do
            source_id = o.obs_source_get_id(source)
            if source_id == "browser_source" then
                local name = o.obs_source_get_name(source)
                o.obs_property_list_add_string(soa, name, name)
            end
        end
    end
    o.source_list_release(sources)

    local scb = o.obs_properties_add_list(p, "sceneb", "Scene B", o.OBS_COMBO_TYPE_EDITABLE, o.OBS_COMBO_FORMAT_STRING)
    local scenes = o.obs_frontend_get_scenes()

    if scenes ~= nil then
        for _, objScene in ipairs(scenes) do
            local scene_source = o.obs_scene_from_source(objScene)
            local scenename = o.obs_source_get_name(objScene)
            o.obs_property_list_add_string(scb, scenename, scenename)
        end
        o.source_list_release(scene_source)
    end
    o.source_list_release(scenes)

    local sob = o.obs_properties_add_list(p, "sourceb", "Scene B Source", o.OBS_COMBO_TYPE_EDITABLE, o.OBS_COMBO_FORMAT_STRING)
    local sources = o.obs_enum_sources()
    if sources ~= nil then
        for _, source in ipairs(sources) do
            local source_id = o.obs_source_get_id(source)
            if source_id == "browser_source" then
                local name = o.obs_source_get_name(source)
                o.obs_property_list_add_string(sob, name, name)
            end
        end
    end
    o.source_list_release(sources)

    return p
end

function script_defaults(s)
    o.obs_data_set_default_bool(s, "enable", false)
end

function script_update(s)
    TEXTFILE = o.obs_data_get_string(s, "theTextFile")
    table.insert(SCENEAB, o.obs_data_get_string(s, "scenea"))
    table.insert(SCENEAB, o.obs_data_get_string(s, "sceneb"))
    table.insert(SOURCEAB, o.obs_data_get_string(s, "sourcea"))
    table.insert(SOURCEAB, o.obs_data_get_string(s, "sourceb"))

    enabled = o.obs_data_get_bool(s, "enable")

    if enabled then
        print("Enabled")
        read_txt_file(TEXTFILE)
        if VIDFILE ~= PVIDFILE then
            refresh_media()
        end
        o.timer_remove(timer_callback)
        o.timer_add(timer_callback, interval)
    else
        print("Disabled")
        o.timer_remove(timer_callback)
    end

end

In Scene A and Scene B, remove or turn off the media sources. Add a browser source to each scene with the following properties (don't worry about filling in the URL path, the script will fill it in).
View attachment 80212

Make sure "Local file" is unchecked.

Add MediaFromTXT3.lua to the OBS scripts. Browse to the mAirList text file. Select the Scene A, Scene A source, Scene B and Scene B source. Check the "Enable script" box. It should start working with instant skipping in the video file.

Let me know how it goes.
So I'm not quite sure how this could happen, but I'm shown the explorer where the TXT file for mAirList is located. Something has gone very wrong there KEKW

1644949782684.png
 

khaver

Member
I wonder if it's the hash mark in "#DOWNLOAD" in the path? Hash marks have a special use in url paths. Is there any way you can use a path without the hash mark?
 

onairmitflo

Member
I wonder if it's the hash mark in "#DOWNLOAD" in the path? Hash marks have a special use in url paths. Is there any way you can use a path without the hash mark?
Oh yeah, I just noticed that too. Even before I read your message hehe. I remove the # sign in the path
 

khaver

Member
Okay, I just tested that. It is the hash mark in the path. I'll see if I can fix it so you don't have to remove it from your path.
 

khaver

Member
Copy and paste this code over the read_txt_file function in MediaFromTXT3.lua refresh the script in OBS. You can keep the hash mark in your path if you want.

Lua:
function read_txt_file(filename)
  filename = filename or ''
  local line
  PVIDFILE = VIDFILE
  if not file_exists(filename) then return end
  for line in io.lines(filename) do
  if line ~= "" then
    VIDFILE = line
    local p, t = line:match("^([^=]+)%;(.+)$")
    if p then
        local path = p:gsub('%#', '%%23')
        VIDPATH = path
        if not t then t = "0" end
        local tsecond = t:gsub('%.', '')
        local ssecond = tsecond:gsub(',', '%.')
        SKIP = ssecond --SKIP = milli
    end
  end
  end
end
 

onairmitflo

Member
Hey, I have news about the functionality in the broadcast mode. Unfortunately, I have the problem that the music has some delay to the video. Just under 1.5sec (due to virtual audio cable and sound processing softwares). Now I need the possibility in the script settings to add a delay when mAirList updates the text file. Do you think this could be implemented?

Problem number 2:
Unfortunately, the loading bars from the Chrome Browser Extension are still visible in OBS for a very short time. Do you think you could move the source in a fade-in every time? With OBS this would be possible by activating and deactivating - maybe you could experiment with that.

Best regards
 

onairmitflo

Member
Hey, I have news about the functionality in the broadcast mode. Unfortunately, I have the problem that the music has some delay to the video. Just under 1.5sec (due to virtual audio cable and sound processing softwares). Now I need the possibility in the script settings to add a delay when mAirList updates the text file. Do you think this could be implemented?

Problem number 2:
Unfortunately, the loading bars from the Chrome Browser Extension are still visible in OBS for a very short time. Do you think you could move the source in a fade-in every time? With OBS this would be possible by activating and deactivating - maybe you could experiment with that.

Best regards
UPDATE:
In mAirList I have now been able to add a delay to the writing of the text file by a trick. The render delay I had applied to the OBS source - was causing these noticeable loading times from Chrome. This is now fixed - mAirList does the delay.

So, kind of killed 2 birds with one stone hehe. I'll still get back to you if I discover another deficiency.
 

andy5211d

New Member
I wonder if I could pose a slightly different problem. This is so close to what I want to do I'm sure one of you cleaver people will know the answer. My problem is that I want to change in code (Lua) the file and location for an Image Source. Basically to change the source from displaying one countrys flag to another. The flags are .png files stored on the local machine. I'm not sure thay are all the same size yet but guess I can edit the .png file somehow. I have spent some time looking through all the formas and help files but so far not found the scripts to change a file location for a Image Source. Seems easy for a Text Source as there are lots of examples on the web but does not work then I use the Image Source name, so there must be more/changed code than I'm using.

Only been using OBS for a few months so still learning and Lua is also new to me.

For the full application of this request please see https://github.com/andy5211d/DR2TVOverlay
 

khaver

Member
Okay, I think I have it for you. This new version of MediaFromTXT should play a random video file from a selected folder while the audio plays. Video files need to be mp4, mov or webm files, preferably without audio. If they do have audio, you'll have to mute them in OBS's audio mixer. If the video file is shorter than the audio file, the video file will loop until the next music video file plays. Once all the files in the random folder have been played, the script will reload them and start picking randomly again.

Whenever the mAirList text file has ;true at the end, a random video file is loaded into a hidden Media Source in the scene and then made visible. Because the Media Source is above the Music Video Source in the Sources list, it will block the Music Video Source but continue to allow it's audio to play.

First, in your SCENE A, add a Media Source and name it something like Random A.
SCENE A.jpg

Random A.jpg

In "Local File" browse to one of the files in your random folder. Set other settings as shown.

Do the same for your SCENE B.
SCENE B.jpg

Open the OBS scripts loader. Remove the old MediaFromTXT script. Unzip the attached new script into your scripts folder and load it.
Scripts.jpg

Fill in the settings as shown.and enable the script with the checkbox.
Try it out and let me know if there are problems.
 

Attachments

  • MediaFromTXT4.zip
    2.2 KB · Views: 28
Last edited:

andy5211d

New Member
Thanks very much, will try later when back home. Just a thought, is there a simple solution so as to be able to 'play' image files (.png or .jpeg) using an Image source rather then a Media source? Perhaps not in this script, but I have tried just changing working scripts on text Sources to call the image Source name (flag):
local source = obs.obs_get_source_by_name(flag)
and then the Settings to:
obs.obs_data_set_string(settings, "image_file", "C:\Users\MyPC\Documents\OBS\mdt\Temp\gbr.png"), etc.,
this seems not to work for an Image Source though?
 
Top