I’m attempting to bookmark video times for my lectures using MPV player and applescript. I log the terminal output of MPV to a text file, and get the script to read the file looking for [bookmark]. The bookmark line is not a function of MPV, but something I’ve mapped to output when I press a key.
My problem is that in a live situation (I’m watching the video, and making bookmarks), the script is looping through all the lines with each iteration and I end up with a list full of duplicates. I know I could clean this up after I quit the video, but I’m going to add a text entry when applescript finds a unique bookmark in the terminal output. So I need to do the filtering as the text file is being read.
Ideally, when the lines of the text file are read the number of lines is assigned to a variable initial_lines. When the text file is read again the number of lines is assigned to current_lines. I then could do (current - initial) +1) to start reading on the next line from the initial_lines.
I missing something subtle (or maybe no so subtle), because the script will work if the text file is complete (I’ve watched the video, made bookmarks, and closed the video & terminal output), but during a live situation its broke.
property line_count : ""
property line_current : "1"
property line_previous : "0"
set {_exit, bmark_list} to {false, {}}
repeat until _exit is true
try
set logs to my get_lines() --sets line_count
set line_current to ((line_count - line_previous) + 1)
repeat with n from line_current to (count of logs)
set str to text of (item n of logs) as string
if str starts with "[bookmark]" then
set _bmark to my get_bmark_info(str, "[bookmark] ", " [/bookmark]")
set _time to item 1 of _bmark
if _time is not in bmark_list then
set end of bmark_list to _bmark
end if
else if str contains "Exiting... (Quit)" then
set _exit to true
end if
end repeat
set line_previous to count of logs
end try
end repeat
return bmark_list
on get_lines()
set temp_file to (POSIX path of (path to temporary items from user domain) & "mpvlogger.txt")
set logs to paragraphs of (read temp_file)
set line_count to count of logs
set line_items to {}
repeat with i from 1 to line_count by 1
if (i + 0) is not greater than line_count then
set end of line_items to items i thru (i + 0) of logs
else
set end of line_items to items i thru line_count of logs
end if
end repeat
return line_items
end get_lines
to get_bmark_info(_line, tag_open, tag_close)
set tid to text item delimiters
set text item delimiters to tag_open
set list_e to text items of _line
set text item delimiters to tag_close
set info to {}
repeat with sub_txt in list_e
if sub_txt contains tag_close then
copy text item 1 of sub_txt to end of info
end if
end repeat
set text item delimiters to tid
set info to info as text
set text item delimiters to ";"
set the_path to text item 1 of info
set the_time to text item 2 of info
set text item delimiters to tid
return {the_time, the_path}
end get_bmark_info
So I got this working, but it’s really hacky, and the repeat loop monitoring the txt file is not very specific. Meaning it reads through the entire file every repeat, and then I grab unique lines with another list.
Another thing I don’t like is that I needed three .scpt files to get this running. I’m almost positive I’m missing something in this regard, and that there is a much better way to achieve this.
set temp_file to (POSIX path of (path to temporary items from user domain) & "mpvlogger.txt")
set vid_file to "/Users/drlulz/Desktop/2013_BECKER_Pathology_01.mp4"
set vid_file_qt to quoted form of vid_file
set vid_file_posix to POSIX file (vid_file) as alias
set proxy_scpt to quoted form of POSIX path of ((path to scripts folder from user domain as text) & "proxy.scpt")
set vid_time to " --start=" & "00:00:00"
set vid_options to quoted form of (" --autofit=100% --save-position-on-quit") --& vid_time)
set cmd_mpv to proxy_scpt & " " & quoted form of temp_file & " " & vid_file_qt & " " & vid_options
set launch_mpv to load script file ((path to scripts folder from user domain as text) & "launch_mpv.scpt")
tell (launch_mpv)
set its _file to temp_file
set its _vid to vid_file_qt
--set its _time to vid_time
set its _options to vid_options
end tell
try
do shell script "rm -f " & temp_file
end try
do shell script "touch " & temp_file
tell application "System Events"
try
set ThePID to unix id of process "mpv"
do shell script "kill -KILL " & ThePID
end try
do shell script "osascript " & cmd_mpv & " &> /dev/null &"
end tell
set {is_bmark, _exit, working_list, bmark_list} to {false, false, {}, {}}
repeat until is_bmark = true
try
set logs to my get_lines()
set is_bmark to true
end try
end repeat
repeat until _exit is true
repeat with n from 1 to (count of logs)
set str to text of (item n of logs) as string
if (str starts with "[bookmark]") and (working_list does not contain str) then
set _bmark to my get_bmark_info(str, "[bookmark] ", " [/bookmark]", bmark_list)
set end of bmark_list to (_bmark & return)
set end of working_list to str
else if str contains "Exiting... (Quit)" then
set _exit to true
end if
set logs to my get_lines()
end repeat
end repeat
if bmark_list is not {} then
my bookmark_txt_file(vid_file_posix, bmark_list, true)
end if
return bmark_list
on get_lines()
set temp_file to (POSIX path of (path to temporary items from user domain) & "mpvlogger.txt")
set logs to paragraphs of (read temp_file)
set line_count to count of logs
set line_items to {}
repeat with i from 1 to line_count by 1
if (i + 0) is not greater than line_count then
set end of line_items to items i thru (i + 0) of logs
else
set end of line_items to items i thru line_count of logs
end if
end repeat
return line_items
end get_lines
to get_bmark_info(_line, tag_open, tag_close, bmark_list)
set tid to text item delimiters
set text item delimiters to tag_open
set list_e to text items of _line
set text item delimiters to tag_close
set info to {}
repeat with sub_txt in list_e
if sub_txt contains tag_close then
copy text item 1 of sub_txt to end of info
end if
end repeat
set text item delimiters to tid
set info to info as text
set text item delimiters to ";"
set the_path to text item 1 of info
set the_time to (text item 2 of info & ";")
set text item delimiters to tid
tell application "mpv"
display dialog "Enter Bookmark Title" default answer "" with title "MPV Bookmark" with icon path to resource "icon.icns" in bundle (path to application "mpv")
set _title to (text returned of the result & ";")
end tell
tell application "System Events"
tell process "mpv" to set W to (name of windows)
tell application process "mpv"
set frontmost to true
set value of attribute "AXMain" of (first window whose name contains W) to true
end tell
end tell
return {_title, the_time, the_path}
end get_bmark_info
on bookmark_txt_file(vid_file, the_report, append_data)
set the_report to the_report as string
tell application "Finder" to set vid_name to text 1 thru ((offset of "." in (name of vid_file as string)) - 1) of (name of vid_file as string)
tell application "Finder" to set vid_folder to container of vid_file as string
set target_file to vid_folder & vid_name & ".txt"
try
set the target_file to target_file as string
set the open_target_file to open for access file target_file with write permission
if append_data is false then set eof of open_target_file to 0
write the_report to open_target_file starting at eof
close access the open_target_file
on error
try
close access file target_file
end try
end try
do shell script "open " & (quoted form of POSIX path of target_file) as string
end bookmark_txt_file
on run argv
set launch_mpv to load script file ((path to scripts folder from user domain as text) & "launch_mpv.scpt")
set temp_file to (item 1 of argv)
set vid_file to (item 2 of argv)
set vid_options to (item 3 of argv)
tell (launch_mpv)
set its _file to temp_file
set its _vid to vid_file
set its _options to vid_options
run
end tell
end run
property _file : ""
property _vid : ""
property _options : ""
do shell script "/usr/local/Cellar/mpv/0.7.3/bin/mpv " & quoted form of _vid & _options & " | tee " & quoted form of _file