iiiJoe 55 Posted December 11, 2023 Author Share Posted December 11, 2023 49 minutes ago, Brian_M said: Here is my scripts I wrote that I use on Linux to solve this problem. While I know this may not help you all out, maybe it will give you some ideas. Here's my ffmpeg script. The real ffmpeg was renamed to ffmpeg.bin #!/bin/bash APP_DIR=/opt/emby-server export AMDGPU_IDS=$APP_DIR/share/libdrm/amdgpu.ids export FONTCONFIG_PATH=$APP_DIR/etc/fonts export LD_LIBRARY_PATH=$APP_DIR/lib:$APP_DIR/extra/lib export LIBVA_DRIVERS_PATH=$APP_DIR/extra/lib/dri export OCL_ICD_VENDORS=$APP_DIR/extra/etc/OpenCL/vendors export PCI_IDS_PATH=$APP_DIR/share/hwdata/pci.ids export SSL_CERT_FILE=$APP_DIR/etc/ssl/certs/ca-certificates.crt $APP_DIR/bin/ffmpeg.bin "$@" if echo $5 | grep recording; then LOGFILE=`echo $5|sed s/graph//` for ((restart = 1; restart <= 10; restart++)); do sleep 5 if ! grep "\[q\] command" $LOGFILE; then echo "*** "`date`" - FAIL - RESTART #"$restart" - ""${52}" - log $LOGFILE >> /var/lib/emby/logs/failed-recordings echo echo "**** recording failed, attempting restart #$restart ****" echo $APP_DIR/bin/ffmpeg.bin $1 $2 $3 $4 "$5" $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15} ${16} ${17} ${18} ${19} "${20}" ${21} ${22} ${23} ${24} ${25} ${26} ${27} ${28} ${29} ${30} ${31} 15 ${33} "${34}" ${35} ${36} ${37} ${38} ${39} ${40} ${41} ${42} ${43} ${44} ${45} ${46} ${47} ${48} ${49} ${50} ${51} -f mpegts - >> "${52}" else break fi done fi Basically all it does is check the log file for "[q] command" and if this doesn't exist, the recording has failed, so it will restart the recording for up to 10 times. After that many restarts, I've found it pointless to try anymore. The recording is just appended to the one that failed. I think I had to add the sleep timer in there to wait until the logs flushed. I've always had to "recopy" IPTV recordings to make comskip work in the first place, but this may be needed to make these files playable after that fact. Here's my postprocessing script. I should probably use a temporary directory to do the recopy in so that Emby doesn't detect it and make .nfo and thumb files for the copy while it's being processed. #!/bin/bash LD_LIBRARY_PATH= ffmpeg -i "$1" -codec copy "$1-fixed.ts" 2> "$1.fix.log" ls -l "$1" >> "$1.fix.log" ls -l "$1-fixed.ts" >> "$1.fix.log" mv "$1-fixed.ts" "$1" rm "$1-fixed.nfo" rm "$1-fixed-thumb.jpg" /usr/bin/comskip --ini=/usr/local/etc/comskip.ini "$1" > "$1-comskip.log" I know this is the Windows forum, so I apologize I'm not much help, but maybe some ideas can be had from this. I'm just very surprised that all of this is needed in the first place really, if I just straight up kill ffmpeg Emby will automatically restart the recording, but it will not do so for these kinds of failures. Btw, I’m very surprised that this is needed as well. Link to comment Share on other sites More sharing options...
joekingcool 26 Posted December 12, 2023 Share Posted December 12, 2023 8 hours ago, iiiJoe said: Not sure why Emby can’t be programmed to restart the recording when “seek to start” fails. agreed ! but after seeing all the updates in the beta, i can see how they have allot on there plate. but for now i think i could make a script/app to do the same. check every min and restart if failed. but im stuck with the cmdline of ffmpeg that's in the failed log file. and that cmd starts the recording back up. 1.but it dont stop when its suppose to too. 2.and it dont create another log file afterwards. example: E:\Emby-Server\system\ffmpeg.exe -loglevel +timing -y -print_graphs_file "E:\Emby-Server\programdata\logs\recording-conversion-c65f64a6-e096-4fca-9370-6fe7a7e25394_1graph.txt" -copyts -start_at_zero -fflags +genpts -analyzeduration 3000000 -f hls -stream_loop -1 -c:v:0 h264 -noautorotate -user_agent "VLC/3.0.0-git LibVLC/3.0.0-git" -multiple_requests 1 -reconnect 1 -reconnect_on_network_error 1 -reconnect_on_http_error 5xx,4xx -reconnect_streamed 1 -reconnect_delay_max 4 -i "https://justsomeurl.m3u8" -map 0:0 -map 0:1 -sn -c:v:0 copy -c:a:0 copy -disposition:a:0 default -avoid_negative_ts disabled -map_metadata -1 -map_chapters -1 "E:\Emby-Server\recordings\Christmas Class Reunion (2022)\Christmas Class Reunion (2022).ts" PS. just would like my wife to not remind me of another failed hallmark Christmas show, and why i choose emby over plex. Link to comment Share on other sites More sharing options...
Brian_M 4 Posted December 12, 2023 Share Posted December 12, 2023 3 hours ago, iiiJoe said: Thank you for this. I will pass it along to my friend. Question: does your script start a new recording or does it continue the previous? Also, does the script stagger the restarts with like 30 second (or some other interval) pauses? It continues the previous recording. It just adds onto it. I think without any postprocessing it will still play back just fine but I usually do that so comskip will work correctly. Link to comment Share on other sites More sharing options...
joekingcool 26 Posted December 12, 2023 Share Posted December 12, 2023 15 minutes ago, Brian_M said: It continues the previous recording. did you post a script or plugin that your able to do this? i think i remember you saying you used linux? if so id be willing to look at the code to see if i can learn something that i could use in windows. Link to comment Share on other sites More sharing options...
Brian_M 4 Posted December 12, 2023 Share Posted December 12, 2023 34 minutes ago, joekingcool said: agreed ! but after seeing all the updates in the beta, i can see how they have allot on there plate. but for now i think i could make a script/app to do the same. check every min and restart if failed. but im stuck with the cmdline of ffmpeg that's in the failed log file. and that cmd starts the recording back up. 1.but it dont stop when its suppose to too. 2.and it dont create another log file afterwards. In my case, Emby still manages to kill the original ffmpeg program it started up which then will kill the child "real ffmpeg" that my script started. I just made a wrapper that so Emby starts my script instead of ffmpeg itself. I think if you could have Emby fire off your script/app instead of ffmpeg directly it would probably work for you too. You don't need to worry about checking the log file until ffmpeg exits to see if it failed so the script/app wouldn't have to be a separate process running in the background the same time the real ffmpeg is running. Link to comment Share on other sites More sharing options...
Brian_M 4 Posted December 12, 2023 Share Posted December 12, 2023 3 minutes ago, joekingcool said: did you post a script or plugin that your able to do this? i think i remember you saying you used linux? if so id be willing to look at the code to see if i can learn something that i could use in windows. Yes, I just posted it today in this topic. I use Emby under Linux so I know it's not super helpful but thought it might give some ideas. Link to comment Share on other sites More sharing options...
joekingcool 26 Posted December 12, 2023 Share Posted December 12, 2023 3 minutes ago, Brian_M said: Yes, I just posted it today in this topic. I use Emby under Linux so I know it's not super helpful but thought it might give some ideas. im going to check it out, thanks! mostly need ffmpeg format i think which should be very similar windows/linux Link to comment Share on other sites More sharing options...
Brian_M 4 Posted December 12, 2023 Share Posted December 12, 2023 15 minutes ago, joekingcool said: im going to check it out, thanks! mostly need ffmpeg format i think which should be very similar windows/linux You'll probably laugh at this but I did make this batch file for @iiiJoeto try out awhile back. I had to convert it to an EXE with a BAT to EXE converter so Emby would run it as ffmpeg.exe. I did have an Emby Windows server setup to test with and it seemed to work as expected. You can have this print out all of the parameters for you. It's only purpose was to change parameter 34 for the recording delay. @echo off set /a count=1 :repeat set /a count+=1 set "params_%count%=%~1" shift if defined params_%count% ( goto :repeat ) else ( set /a count-=1 ) set /a params_0=count setlocal enabledelayedexpansion for /l %%i in (1,1,!params_0!) do ( echo params_%%i: "!params_%%i!" ) REM check graph file for the word recording and substitute param 34, reconnect_delay_max set str1=%params_6% if x%str1:recording=%==x%str1% goto not_recording echo. echo This is a recording... echo. echo Executing ffmpeg-bin.exe !params_2! !params_3! !params_4! !params_5! "!params_6!" !params_7! !params_8! !params_9! !params_10! !params_11! !params_12! !params_13! !params_14! !params_15! !params_16! !params_17! !params_18! "!params_19!" "!params_20!" "!params_21!" !params_22! !params_23! !params_24! !params_25! !params_26! !params_27! !params_28! !params_29!,!params_30! !params_31! !params_32! !params_33! 127 !params_35! !params_36! !params_37! !params_38! !params_39! !params_40! !params_41! !params_42! !params_43! !params_44! !params_45! !params_46! !params_47! !params_48! !params_49! !params_50! !params_51! !params_52! !params_53! "!params_54!" !params_55! !params_56! !params_57! !params_58! !params_59! !params_60! !params_61! !params_62! !params_63! !params_64! !params_65! !params_66! !params_67! !params_68! !params_69! !params_70! !params_71! !params_72! !params_73! !params_74! !params_75! !params_76! !params_77! !params_78! !params_79! !params_80! !params_81! !params_82! !params_83! !params_84! !params_85! !params_86! !params_87! !params_88! !params_89! !params_90! !params_91! !params_92! !params_93! !params_94! !params_95! !params_96! !params_97! !params_98! !params_99! !params_100! !params_101! !params_102! !params_103! !params_104! !params_105! !params_106! !params_107! !params_108! !params_109! ffmpeg-bin.exe !params_2! !params_3! !params_4! !params_5! "!params_6!" !params_7! !params_8! !params_9! !params_10! !params_11! !params_12! !params_13! !params_14! !params_15! !params_16! !params_17! !params_18! "!params_19!" "!params_20!" "!params_21!" !params_22! !params_23! !params_24! !params_25! !params_26! !params_27! !params_28! !params_29!,!params_30! !params_31! !params_32! !params_33! 127 !params_35! !params_36! !params_37! !params_38! !params_39! !params_40! !params_41! !params_42! !params_43! !params_44! !params_45! !params_46! !params_47! !params_48! !params_49! !params_50! !params_51! !params_52! !params_53! "!params_54!" !params_55! !params_56! !params_57! !params_58! !params_59! !params_60! !params_61! !params_62! !params_63! !params_64! !params_65! !params_66! !params_67! !params_68! !params_69! !params_70! !params_71! !params_72! !params_73! !params_74! !params_75! !params_76! !params_77! !params_78! !params_79! !params_80! !params_81! !params_82! !params_83! !params_84! !params_85! !params_86! !params_87! !params_88! !params_89! !params_90! !params_91! !params_92! !params_93! !params_94! !params_95! !params_96! !params_97! !params_98! !params_99! !params_100! !params_101! !params_102! !params_103! !params_104! !params_105! !params_106! !params_107! !params_108! !params_109! exit :not_recording echo. echo This is not a recording... echo. echo Executing ffmpeg-bin.exe !params_2! !params_3! !params_4! !params_5! !params_6! !params_7! !params_8! !params_9! !params_10! !params_11! !params_12! !params_13! !params_14! !params_15! !params_16! !params_17! !params_18! "!params_19!" "!params_20!" "!params_21!" !params_22! !params_23! !params_24! !params_25! !params_26! !params_27!,!params_28! !params_29! !params_30! !params_31! !params_32! !params_33! !params_34! !params_35! !params_36! !params_37! !params_38! !params_39! !params_40! !params_41! !params_42! !params_43! !params_44! !params_45! !params_46! !params_47! !params_48! !params_49! !params_50! !params_51! !params_52! !params_53! !params_54! !params_55! !params_56! !params_57! !params_58! !params_59! !params_60! !params_61! !params_62! !params_63! !params_64! !params_65! !params_66! !params_67! !params_68! !params_69! !params_70! !params_71! !params_72! !params_73! !params_74! !params_75! !params_76! !params_77! !params_78! !params_79! !params_80! !params_81! !params_82! !params_83! !params_84! !params_85! !params_86! !params_87! !params_88! !params_89! !params_90! !params_91! !params_92! !params_93! !params_94! !params_95! !params_96! !params_97! !params_98! !params_99! !params_100! !params_101! !params_102! !params_103! !params_104! !params_105! !params_106! !params_107! !params_108! !params_109! echo. ffmpeg-bin.exe !params_2! !params_3! !params_4! !params_5! !params_6! !params_7! !params_8! !params_9! !params_10! !params_11! !params_12! !params_13! !params_14! !params_15! !params_16! !params_17! !params_18! "!params_19!" "!params_20!" "!params_21!" !params_22! !params_23! !params_24! !params_25! !params_26! !params_27!,!params_28! !params_29! !params_30! !params_31! !params_32! !params_33! !params_34! !params_35! !params_36! !params_37! !params_38! !params_39! !params_40! !params_41! !params_42! !params_43! !params_44! !params_45! !params_46! !params_47! !params_48! !params_49! !params_50! !params_51! !params_52! !params_53! !params_54! !params_55! !params_56! !params_57! !params_58! !params_59! !params_60! !params_61! !params_62! !params_63! !params_64! !params_65! !params_66! !params_67! !params_68! !params_69! !params_70! !params_71! !params_72! !params_73! !params_74! !params_75! !params_76! !params_77! !params_78! !params_79! !params_80! !params_81! !params_82! !params_83! !params_84! !params_85! !params_86! !params_87! !params_88! !params_89! !params_90! !params_91! !params_92! !params_93! !params_94! !params_95! !params_96! !params_97! !params_98! !params_99! !params_100! !params_101! !params_102! !params_103! !params_104! !params_105! !params_106! !params_107! !params_108! !params_109! goto :eof Link to comment Share on other sites More sharing options...
joekingcool 26 Posted December 12, 2023 Share Posted December 12, 2023 6 minutes ago, Brian_M said: You'll probably laugh at this yes for so many reasons. lol i just was thinking the language would be similar. this shows im not much of coder. also i just asked my buddy whos a powershell and bash guru to convert it. hes probably laughing at me right now. lol i usually do autohotkey and muddle my way threw with allot of help from online. Link to comment Share on other sites More sharing options...
Brian_M 4 Posted December 12, 2023 Share Posted December 12, 2023 10 minutes ago, joekingcool said: yes for so many reasons. lol i just was thinking the language would be similar. this shows im not much of coder. also i just asked my buddy whos a powershell and bash guru to convert it. hes probably laughing at me right now. lol i usually do autohotkey and muddle my way threw with allot of help from online. Sounds like you've got some awesome help! I'm not a programmer either by any means. Unfortunately my Windows skills are very lacking. It was a challenge just to make that work lol. I hope you all are able to come up with something, gotta try to keep the wives/girlfriends happy! 2 Link to comment Share on other sites More sharing options...
joekingcool 26 Posted December 12, 2023 Share Posted December 12, 2023 20 minutes ago, Brian_M said: It's only purpose was to change parameter 34 for the recording delay oh ok... so you convert this batch to exe, and label exe as ffmpeg.exe . so that emby uses the custom ffmpeg which creates the real ffmpeg as a subprocess. i seen where it was suggested by changing that param, that it help it stay alive. but i didnt know that solved it. i get "seek to failed" the rest emby seems to recover from. Link to comment Share on other sites More sharing options...
Brian_M 4 Posted December 12, 2023 Share Posted December 12, 2023 7 minutes ago, joekingcool said: oh ok... so you convert this batch to exe, and label exe as ffmpeg.exe . so that emby uses the custom ffmpeg which creates the real ffmpeg as a subprocess. i seen where it was suggested by changing that param, that it help it stay alive. but i didnt know that solved it. i get "seek to failed" the rest emby seems to recover from. Yep, that's what it does. That's as far as I got with it. Unfortunately, changing that param does not fix the "seek to failed" message though. Link to comment Share on other sites More sharing options...
joekingcool 26 Posted December 12, 2023 Share Posted December 12, 2023 5 minutes ago, Brian_M said: does not fix the "seek to failed" message though. does your bash script do the same thing? Link to comment Share on other sites More sharing options...
Brian_M 4 Posted December 12, 2023 Share Posted December 12, 2023 Just now, joekingcool said: does your bash script do the same thing? It does change that param to 15, which ended up being a good number for me, but they key is it checks the log file after ffmpeg exits for "[q] command" This is what Emby seems to send ffmpeg and is logged when the recording was successful. You may see something different in Windows though, but I imagine it's quite similar. If it fails for any other reason, like "seek to failed" or whatever, that will not be in the log file and the script will go through a loop where it tries to restart "real ffmpeg" for up to 10 times to finish the recording. FYI, even if the recording finished successfully after a restart, you will never see the "[q] command" in the logs, but Emby manages to kill the ffmpeg process when the recording time is up anyway. Link to comment Share on other sites More sharing options...
joekingcool 26 Posted December 12, 2023 Share Posted December 12, 2023 7 minutes ago, Brian_M said: Emby manages to kill the ffmpeg process when the recording time is up anyway. you got my gears turning about this wrapper thing. to get the parms that emby is sending to ffmpeg. im going to look into that. i was running the cmd in the log file. which started the recording on same channel. but it didnt know when to stop... Link to comment Share on other sites More sharing options...
iiiJoe 55 Posted December 12, 2023 Author Share Posted December 12, 2023 2 hours ago, Brian_M said: You'll probably laugh at this but I did make this batch file for @iiiJoeto try out awhile back. I had to convert it to an EXE with a BAT to EXE converter so Emby would run it as ffmpeg.exe. I did have an Emby Windows server setup to test with and it seemed to work as expected. You can have this print out all of the parameters for you. It's only purpose was to change parameter 34 for the recording delay. @echo off set /a count=1 :repeat set /a count+=1 set "params_%count%=%~1" shift if defined params_%count% ( goto :repeat ) else ( set /a count-=1 ) set /a params_0=count setlocal enabledelayedexpansion for /l %%i in (1,1,!params_0!) do ( echo params_%%i: "!params_%%i!" ) REM check graph file for the word recording and substitute param 34, reconnect_delay_max set str1=%params_6% if x%str1:recording=%==x%str1% goto not_recording echo. echo This is a recording... echo. echo Executing ffmpeg-bin.exe !params_2! !params_3! !params_4! !params_5! "!params_6!" !params_7! !params_8! !params_9! !params_10! !params_11! !params_12! !params_13! !params_14! !params_15! !params_16! !params_17! !params_18! "!params_19!" "!params_20!" "!params_21!" !params_22! !params_23! !params_24! !params_25! !params_26! !params_27! !params_28! !params_29!,!params_30! !params_31! !params_32! !params_33! 127 !params_35! !params_36! !params_37! !params_38! !params_39! !params_40! !params_41! !params_42! !params_43! !params_44! !params_45! !params_46! !params_47! !params_48! !params_49! !params_50! !params_51! !params_52! !params_53! "!params_54!" !params_55! !params_56! !params_57! !params_58! !params_59! !params_60! !params_61! !params_62! !params_63! !params_64! !params_65! !params_66! !params_67! !params_68! !params_69! !params_70! !params_71! !params_72! !params_73! !params_74! !params_75! !params_76! !params_77! !params_78! !params_79! !params_80! !params_81! !params_82! !params_83! !params_84! !params_85! !params_86! !params_87! !params_88! !params_89! !params_90! !params_91! !params_92! !params_93! !params_94! !params_95! !params_96! !params_97! !params_98! !params_99! !params_100! !params_101! !params_102! !params_103! !params_104! !params_105! !params_106! !params_107! !params_108! !params_109! ffmpeg-bin.exe !params_2! !params_3! !params_4! !params_5! "!params_6!" !params_7! !params_8! !params_9! !params_10! !params_11! !params_12! !params_13! !params_14! !params_15! !params_16! !params_17! !params_18! "!params_19!" "!params_20!" "!params_21!" !params_22! !params_23! !params_24! !params_25! !params_26! !params_27! !params_28! !params_29!,!params_30! !params_31! !params_32! !params_33! 127 !params_35! !params_36! !params_37! !params_38! !params_39! !params_40! !params_41! !params_42! !params_43! !params_44! !params_45! !params_46! !params_47! !params_48! !params_49! !params_50! !params_51! !params_52! !params_53! "!params_54!" !params_55! !params_56! !params_57! !params_58! !params_59! !params_60! !params_61! !params_62! !params_63! !params_64! !params_65! !params_66! !params_67! !params_68! !params_69! !params_70! !params_71! !params_72! !params_73! !params_74! !params_75! !params_76! !params_77! !params_78! !params_79! !params_80! !params_81! !params_82! !params_83! !params_84! !params_85! !params_86! !params_87! !params_88! !params_89! !params_90! !params_91! !params_92! !params_93! !params_94! !params_95! !params_96! !params_97! !params_98! !params_99! !params_100! !params_101! !params_102! !params_103! !params_104! !params_105! !params_106! !params_107! !params_108! !params_109! exit :not_recording echo. echo This is not a recording... echo. echo Executing ffmpeg-bin.exe !params_2! !params_3! !params_4! !params_5! !params_6! !params_7! !params_8! !params_9! !params_10! !params_11! !params_12! !params_13! !params_14! !params_15! !params_16! !params_17! !params_18! "!params_19!" "!params_20!" "!params_21!" !params_22! !params_23! !params_24! !params_25! !params_26! !params_27!,!params_28! !params_29! !params_30! !params_31! !params_32! !params_33! !params_34! !params_35! !params_36! !params_37! !params_38! !params_39! !params_40! !params_41! !params_42! !params_43! !params_44! !params_45! !params_46! !params_47! !params_48! !params_49! !params_50! !params_51! !params_52! !params_53! !params_54! !params_55! !params_56! !params_57! !params_58! !params_59! !params_60! !params_61! !params_62! !params_63! !params_64! !params_65! !params_66! !params_67! !params_68! !params_69! !params_70! !params_71! !params_72! !params_73! !params_74! !params_75! !params_76! !params_77! !params_78! !params_79! !params_80! !params_81! !params_82! !params_83! !params_84! !params_85! !params_86! !params_87! !params_88! !params_89! !params_90! !params_91! !params_92! !params_93! !params_94! !params_95! !params_96! !params_97! !params_98! !params_99! !params_100! !params_101! !params_102! !params_103! !params_104! !params_105! !params_106! !params_107! !params_108! !params_109! echo. ffmpeg-bin.exe !params_2! !params_3! !params_4! !params_5! !params_6! !params_7! !params_8! !params_9! !params_10! !params_11! !params_12! !params_13! !params_14! !params_15! !params_16! !params_17! !params_18! "!params_19!" "!params_20!" "!params_21!" !params_22! !params_23! !params_24! !params_25! !params_26! !params_27!,!params_28! !params_29! !params_30! !params_31! !params_32! !params_33! !params_34! !params_35! !params_36! !params_37! !params_38! !params_39! !params_40! !params_41! !params_42! !params_43! !params_44! !params_45! !params_46! !params_47! !params_48! !params_49! !params_50! !params_51! !params_52! !params_53! !params_54! !params_55! !params_56! !params_57! !params_58! !params_59! !params_60! !params_61! !params_62! !params_63! !params_64! !params_65! !params_66! !params_67! !params_68! !params_69! !params_70! !params_71! !params_72! !params_73! !params_74! !params_75! !params_76! !params_77! !params_78! !params_79! !params_80! !params_81! !params_82! !params_83! !params_84! !params_85! !params_86! !params_87! !params_88! !params_89! !params_90! !params_91! !params_92! !params_93! !params_94! !params_95! !params_96! !params_97! !params_98! !params_99! !params_100! !params_101! !params_102! !params_103! !params_104! !params_105! !params_106! !params_107! !params_108! !params_109! goto :eof Really appreciated it too!!! Hoping we can get this ironed out Link to comment Share on other sites More sharing options...
iiiJoe 55 Posted December 12, 2023 Author Share Posted December 12, 2023 “Seek to start failed” is virtually the only issue for me as well Link to comment Share on other sites More sharing options...
joekingcool 26 Posted December 12, 2023 Share Posted December 12, 2023 20 hours ago, joekingcool said: Emby manages to kill the ffmpeg process when the recording time is up anyway. well i made a wrapper with ahk to see the params its passing threw. it shows them all. although emby keeps sending same cmd about every min or so. so im guessing thats its way of keeping it alive. also it didnt run hardware log correctly. i did get your batch/exe to work although not for the seek error. still not giving up yet Link to comment Share on other sites More sharing options...
joekingcool 26 Posted December 12, 2023 Share Posted December 12, 2023 thought id post the few scripts i made to help for windows users in ahk. you can compile to exe or i can for you if you would like. 1 deletes *.jpg *.nfo and empty folders from recordings folder. dir= E:\Emby-Server\recordings Loop, Files, %dir%\*.jpg, FR FileDelete, %A_LoopFileFullPath% Loop, Files, %dir%\*.nfo, FR FileDelete, %A_LoopFileFullPath% Loop, Files, % dir . "\*", DR { if DllCall("Shlwapi\PathIsDirectoryEmpty", "Str", A_LoopFilePath) FileRemoveDir, %A_LoopFilePath% } if DllCall("Shlwapi\PathIsDirectoryEmpty", "Str", parentFolder) FileRemoveDir, %dir% Loop, Files, % dir . "\*", DR { if DllCall("Shlwapi\PathIsDirectoryEmpty", "Str", A_LoopFilePath) FileRemoveDir, %A_LoopFilePath% } if DllCall("Shlwapi\PathIsDirectoryEmpty", "Str", parentFolder) FileRemoveDir, %dir% 2. easly remove old recordings from embys timers. sleep 3000 KEY := [] KEY[j, k] := A_LoopReadLine KEYCount := 0 Loop, Read, %A_ScriptDir%\custom.txt { KEYCount += 1 KEY[KEYCount] := A_LoopReadLine } Loop % KEYCount { element := KEY[A_Index] } password := KEY[3] runwait, curl -X POST "http://localhost:8096/emby/System/Shutdown?api_key=%password%" ,,hide Movies_New := "" Movies_All := "" Movies_Brief := "" Recordings_All := "" Recordings_Brief := "" Find_Movie := "" Find_Movies := "`"`":`"`"MV" Fileread, file, % KEY[1]"\timers.json" arr := Jxon_Load(file) ;----------------format ALL recordings, export to VAR Recordings_All---------------- for each, obj in arr Recordings_All .= "{`"`"ProviderIds`"`":{},`"`"SeriesProviderIds`"`":{},`"`"Tags`"`":[],`"`"Id`"`":`"`"" obj.Id "`"`",`"`"ChannelId`"`":`"`"" obj.ChannelId "`"`",`"`"ProgramId`"`":`"`"" obj.ProgramId "`"`",`"`"Name`"`":`"`"" obj.Name "`"`",`"`"Overview`"`":`"`"" obj.Overview "`"`",`"`"SeriesId`"`":`"`"" obj.SeriesId "`"`",`"`"StartDate`"`":`"`"" obj.StartDate "`"`",`"`"EndDate`"`":`"`"" obj.EndDate "`"`",`"`"Status`"`":`"`"" obj.Status "`"`",`"`"PrePaddingSeconds`"`":" obj.PrePaddingSeconds ",`"`"PostPaddingSeconds`"`":" obj.PostPaddingSeconds ",`"`"IsPrePaddingRequired`"`":false,`"`"IsPostPaddingRequired`"`":false,`"`"IsManual`"`":true,`"`"Priority`"`":0,`"`"RetryCount`"`":0,`"`"IsMovie`"`":true,`"`"IsKids`"`":false,`"`"IsSports`"`":false,`"`"IsNews`"`":false,`"`"IsSeries`"`":false,`"`"IsLive`"`":false,`"`"IsPremiere`"`":false,`"`"ProductionYear`"`":" obj.ProductionYear ",`"`"IsProgramSeries`"`":false,`"`"IsRepeat`"`":false,`"`"IsNew`"`":false,`"`"OfficialRating`"`":`"`"" obj.OfficialRating "`"`",`"`"Genres`"`":[],`"`"KeepUntil`"`":`"`"UntilDeleted`"`"}," "`n" ;--------find movieS and export to VAR Movie_All--------------- Loop, Parse, Recordings_All, `n, `r If instr(A_LoopField, Find_Movies) Movies_All .= A_LoopField "`n" ;----------------Brief format ALL recordings, export to VAR Recordings_All---------------- for each, obj in arr Recordings_Brief .= obj.StartDate "`"`":`"`"" obj.SeriesId " " obj.Name "`n" ;--------brief find movieS and export to VAR Movie_All--------------- Loop, Parse, Recordings_Brief, `n, `r If instr(A_LoopField, Find_Movies) Movies_Brief .= A_LoopField "`n" StringReplace, Movies_Brief, Movies_Brief, .0000000Z, , All StringReplace, Movies_Brief, Movies_Brief, ":", , All Movies_Brief := RegExReplace(Movies_Brief, "MV\d{12}") msgbox, %Movies_Brief% begin: Gui, Destroy Gui, New Gui, Add, Edit, w180 h20 vFind_Movie, Gui, Add, Button, w180 h20 gRemove, Remove gui, show, , THE GUI return GuiClose: loc := KEY[2] run, %loc%\EmbyServer.exe ,,hide ExitApp Remove: Gui, Submit, NoHide ;--------find movie and remove from movieS and export to VAR Movies_New--------------- Loop, Parse, Movies_All, `n, `r If Not instr(A_LoopField, Find_Movie) Movies_New .= A_LoopField "`n" Movies_All := Movies_New Movies_New := "" StringReplace, json, Movies_All, `n, , All StringTrimRight, json, json, 1 json = [%json%] FileDelete, % KEY[1]"\timers.json" FileAppend, %json%, % KEY[1]"\timers.json" ;--------find movie and remove from movieS and export to VAR Movies_New--------------- Loop, Parse, Movies_Brief, `n, `r If Not instr(A_LoopField, Find_Movie) Movies_New .= A_LoopField "`n" Movies_Brief := Movies_New Movies_New := "" StringReplace, Movies_Brief, Movies_Brief, .0000000Z, , All StringReplace, Movies_Brief, Movies_Brief, ":", , All msgbox, %Movies_Brief% goto, begin ; ------------------------------------------------------------------------------------------------------------------------- ; Coco's Jxon_Load function: https://github.com/cocobelgica/AutoHotkey-JSON/blob/master/Jxon.ahk Jxon_Load(ByRef src, args*) { static q := Chr(34) key := "", is_key := false stack := [ tree := [] ] is_arr := { (tree): 1 } next := q . "{[01234567890-tfn" pos := 0 while ( (ch := SubStr(src, ++pos, 1)) != "" ) { if InStr(" `t`n`r", ch) continue if !InStr(next, ch, true) { ln := ObjLength(StrSplit(SubStr(src, 1, pos), "`n")) col := pos - InStr(src, "`n",, -(StrLen(src)-pos+1)) msg := Format("{}: line {} col {} (char {})" , (next == "") ? ["Extra data", ch := SubStr(src, pos)][1] : (next == "'") ? "Unterminated string starting at" : (next == "\") ? "Invalid \escape" : (next == ":") ? "Expecting ':' delimiter" : (next == q) ? "Expecting object key enclosed in double quotes" : (next == q . "}") ? "Expecting object key enclosed in double quotes or object closing '}'" : (next == ",}") ? "Expecting ',' delimiter or object closing '}'" : (next == ",]") ? "Expecting ',' delimiter or array closing ']'" : [ "Expecting JSON value(string, number, [true, false, null], object or array)" , ch := SubStr(src, pos, (SubStr(src, pos)~="[\]\},\s]|$")-1) ][1] , ln, col, pos) throw Exception(msg, -1, ch) } is_array := is_arr[obj := stack[1]] if i := InStr("{[", ch) { val := (proto := args[i]) ? new proto : {} is_array? ObjPush(obj, val) : obj[key] := val ObjInsertAt(stack, 1, val) is_arr[val] := !(is_key := ch == "{") next := q . (is_key ? "}" : "{[]0123456789-tfn") } else if InStr("}]", ch) { ObjRemoveAt(stack, 1) next := stack[1]==tree ? "" : is_arr[stack[1]] ? ",]" : ",}" } else if InStr(",:", ch) { is_key := (!is_array && ch == ",") next := is_key ? q : q . "{[0123456789-tfn" } else ; string | number | true | false | null { if (ch == q) ; string { i := pos while i := InStr(src, q,, i+1) { val := StrReplace(SubStr(src, pos+1, i-pos-1), "\\", "\u005C") static end := A_AhkVersion<"2" ? 0 : -1 if (SubStr(val, end) != "\") break } if !i ? (pos--, next := "'") : 0 continue pos := i ; update pos val := StrReplace(val, "\/", "/") , val := StrReplace(val, "\" . q, q) , val := StrReplace(val, "\b", "`b") , val := StrReplace(val, "\f", "`f") , val := StrReplace(val, "\n", "`n") , val := StrReplace(val, "\r", "`r") , val := StrReplace(val, "\t", "`t") i := 0 while i := InStr(val, "\",, i+1) { if (SubStr(val, i+1, 1) != "u") ? (pos -= StrLen(SubStr(val, i)), next := "\") : 0 continue 2 ; \uXXXX - JSON unicode escape sequence xxxx := Abs("0x" . SubStr(val, i+2, 4)) if (A_IsUnicode || xxxx < 0x100) val := SubStr(val, 1, i-1) . Chr(xxxx) . SubStr(val, i+6) } if is_key { key := val, next := ":" continue } } else ; number | true | false | null { val := SubStr(src, pos, i := RegExMatch(src, "[\]\},\s]|$",, pos)-pos) ; For numerical values, numerify integers and keep floats as is. ; I'm not yet sure if I should numerify floats in v2.0-a ... static number := "number", integer := "integer" if val is %number% { if val is %integer% val += 0 } ; in v1.1, true,false,A_PtrSize,A_IsUnicode,A_Index,A_EventInfo, ; SOMETIMES return strings due to certain optimizations. Since it ; is just 'SOMETIMES', numerify to be consistent w/ v2.0-a else if (val == "true" || val == "false") val := %value% + 0 ; AHK_H has built-in null, can't do 'val := %value%' where value == "null" ; as it would raise an exception in AHK_H(overriding built-in var) else if (val == "null") val := "" ; any other values are invalid, continue to trigger error else if (pos--, next := "#") continue pos += i-1 } is_array? ObjPush(obj, val) : obj[key] := val next := obj==tree ? "" : is_array ? ",]" : ",}" } } return tree[1] } 3. easy see what shows failed with seek to start error. File := "E:\Emby-Server\programdata\logs\*.txt" StringCheck := "Seek to start failed" FileHit:="" path:="" video:="" Loop, %File%, , 1 { FileRead, FileCheck, %A_LoopFileLongPath% IfInString, FileCheck, %StringCheck% { FileHit%A_Index% := A_LoopFilePath FileRead, string, %A_LoopFileLongPath% failed := BetweenWords(string, "-map_chapters -1 """, ".ts") path := failed[1] SplitPath, path, name video .= name "`n" } } Loop, 10000 { If (FileHit%A_Index% <> "") FileHit .= FileHit%A_Index% . "`n" } if (FileHit = "") exitapp if (FileHit != "") msgbox, %video% ;MsgBox, % FileHit BetweenWords(string, before, after) { arr := [] template := "\Q" . before . "\E(.*?)\Q" . after . "\E" while pos := RegExMatch(string, template, Match, pos ? pos + StrLen(Match) : 1) { arr.Push(Match1) } Return arr } Link to comment Share on other sites More sharing options...
iiiJoe 55 Posted December 14, 2023 Author Share Posted December 14, 2023 On 12/12/2023 at 5:43 PM, joekingcool said: 3. easy see what shows failed with seek to start error. Sorry guys but this is all Greek to me. Are you saying the script is showing why the “seek to start error” was triggered? Link to comment Share on other sites More sharing options...
joekingcool 26 Posted December 14, 2023 Share Posted December 14, 2023 8 hours ago, iiiJoe said: Sorry guys but this is all Greek to me. Are you saying the script is showing why the “seek to start error” was triggered? no it just shows you a list of shows that failed because of that error. i have it run every second then have it send me a text msg with another app i made. so i can restart as soon as possible. the reason is most likely the provider changing streams and/or recording shows back to back on same channel and you set the pre/post recording time. i still feel emby could monitor for this unique error like me and redo the recording from that point. with this error ffmpeg dont give a exit cmd and emby or ffmpeg dont try to restart. so its not the typical ffmpeg error. this is what ive learned over the past couple weeks. but not sure, im a noob as well. Link to comment Share on other sites More sharing options...
iiiJoe 55 Posted December 19, 2023 Author Share Posted December 19, 2023 Emby team, any input on a fix or work around for the "seek to start failed" error would be appreciated..... Link to comment Share on other sites More sharing options...
joekingcool 26 Posted December 21, 2023 Share Posted December 21, 2023 i made an app and done the followup on other thread. sorry my mistake. let me know how it works!! ServiceSecurityEditor.exe Record_Monitor.exe Emby Server.url nssm.exe Record_Monitor.ahk.txt Link to comment Share on other sites More sharing options...
iiiJoe 55 Posted December 21, 2023 Author Share Posted December 21, 2023 (edited) 2 hours ago, joekingcool said: i made an app and done the followup on other thread. sorry my mistake. let me know how it works!! ServiceSecurityEditor.exe 430.29 kB · 0 downloads Record_Monitor.exe 2.91 MB · 0 downloads Emby Server.url 69 B · 0 downloads nssm.exe 323.5 kB · 0 downloads Record_Monitor.ahk.txt 12.17 kB · 0 downloads Amazing work!! I have a few questions. Does this create a new recording? Or, does it just add to the existing recording file? Are you using this on Windows? When it detects a failed recording is the entire Emby program closed and re-started or does it simply re-start the recording. Just wondering if this affects others users on the server during the re-start. What has been your success rate on re-starting “seek to start failed” recordings? Again, amazing job!! Edited December 21, 2023 by iiiJoe Link to comment Share on other sites More sharing options...
joekingcool 26 Posted December 21, 2023 Share Posted December 21, 2023 (edited) thanks! it creates new recording like emby normally would in the same format -1 -2 etc. but i have a script when you run it, its searches threw record folder and uses ffmpeg to splice together. having figured out proper logic yet to integrate them both together yet, but soon i assume , time permitting. yes using on windows 10 updated. yes when it detects it shutdown emby so it can modify the timers.json file that emby uses for recordings, then starts back up. my provider noticed i was testing multiple stream earlier in the testing period and limited me back to 5 streams at time. so recently i tested 3 stream multiple times and less than minute later they where all recording again. yesterday the failure rate was high. today i think i worked them all out. did multiple dozens in row, that it all successfully restarted. not saying its perfect but it should be pretty close. you can hold off for month or 2 and wait to see long term or test it out your self. i created a simple firewall rule in windows to block ffmpeg outgoing. togged on/off blocking ffmpeg to trigger failed start error in log. then watched it fix in less then minute. ive spent all today and most yesterday testing different types of situations the videos file format would be in. then using allot of regex to format so it would match with what's in the json file. btw it needs to be placed next to the system folder for emby and the recording folder needs to be next to the system folder. that's just how i have it setup on my pc. but uses relative placement so it can be portable. i needed emby to be run as a service for couple reasons. easier safe shutdown / startup and in my app if i shutdown like others on here using curl i was fine, but when i started it back up it was seen running under my app, which then made it a problem for the app to startup and shutdown. plus the other way the user would have to generate an api key bla bla sorry im just excited to not have to hear multiple times a week another failed recording .... restarting the recording independently of emby was a nightmare to do reliably. the other scripts i have does a great job at spicing them together. Edited December 21, 2023 by joekingcool Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now