mediacowboy needed something to help find videos that wouldn't play directly on the Roku, but ended up required transcoding to do so.
This only detects at present very basic reasons a file might fail.
Container not mkv, mp4, mov, m4v, m3u8, ts
Video Codec not H.264
Audio Codec not AC3 or Stero AAC
Install AutoIt and set it to execute scripts when double clicked.
Create a folder somewhere...lets call it "Roku Detect uncompliant Videos" just to be unimaginative.
Now inside "Roku Detect Uncompliant Videos" create a sub folder called "Bin".
Now extract the contents of FFMpeg's "Bin" folder into your new "Bin" sub folder.
Now going back into "Roku Detect Uncompliant Videos" folder Right Click on it's background and select "New\AutoIt v3 Script" from the context menu, and Rename it "Roku Detect Uncompliant Videos.au3"
Now Right Click "Roku Detect Uncompliant Videos.au3" & select "Edit Script" from the context menu.
Now paste the following code into:
#Include <Array.au3> #Include <File.au3> #Include <String.au3> Dim $aKnown = [6 , '.mkv' , '.mp4' , '.mov' , '.m4v' , '.m3u8' , '.ts'] Dim $aUnknown =  Dim $sErrorLog ; Select Video Folder While 1 $sFolder = FileSelectFolder( 'Select Video Folder.' , '' , 6 ) If @Error = 1 AND $sFolder = '' Then MsgBox( 4096 , 'Exit:' , 'Ending Application' ) Exit ElseIf $sFolder = '' Then MsgBox( 4096 , 'Error:' , 'Unable To Open Folder.' ) ElseIf NOT FileExists ( $sFolder ) Then MsgBox( 4096 , 'Error:' , 'Invalid Folder.' ) Else If StringRight( $sFolder , 1 ) <> '\' Then $sFolder &= '\' $aAllFiles = _FileListToArrayRec( $sFolder , '*.*|*.bif;*.db;*.jpg;*.nfo;*.png;*.tbn;*.xml;*.srt;*.sub;*.ssa;*.mp3' , 1 , 1 , 0 , 2 ) If NOT IsArray( $aAllFiles ) Then MsgBox( 4096 , 'Error:' , 'No Videos Found.' ) Else _ArraySort( $aAllFiles , 0 , 1 ) ExitLoop EndIf EndIf WEnd For $ii = 1 To $aAllFiles _Macros( $aAllFiles[$ii] ) $iFind1 = _ArraySearch( $aKnown , $sFileExt , 1 ) If @Error Then $sErrorLog &= 'Unknown File Type:' & @CRLF & $aAllFiles[$ii] & @CRLF & @CRLF $iFind2 = _ArraySearch( $aUnknown , $sFileExt , 1 ) If @Error Then _ArrayAdd( $aUnknown , $sFileExt ) $aUnknown += 1 EndIf Else ; Build Array of Streams $sRandomString = _RandomString() RunWait( @ComSpec & ' /c ffprobe -show_streams "' & $aAllFiles[$ii] & '">"' & @TempDir & '\' & $sRandomString & '.txt"' , @ScriptDir & '\BIN\' , @SW_HIDE ) $aAllStreams = _StringBetween( FileRead( @TempDir & '\' & $sRandomString & '.txt' ) , '[STREAM]' , '[/STREAM]' ) FileDelete( @TempDir & '\' & $sRandomString & '.txt' ) ; Find Video Streams $aFindVideoStreams = _ArrayFindAll( $aAllStreams , 'codec_type=video' , 0 , 0 , 0 , 1 ) If $aFindVideoStreams <> -1 Then ; Process Video Streams For $aa = 0 To UBound( $aFindVideoStreams ) - 1 $sSVideoCodec = _RegExString( $aAllStreams[$aFindVideoStreams[$aa]] , '(?s)(?i)(?:.+?codec_name=(\S+))?' ) If $sSVideoCodec <> 'h264' And $sSVideoCodec <> 'mpeg4' Then $sErrorLog &= 'Unsupported Video Codec: (' & $sSVideoCodec & ')' & @CRLF & $aAllFiles[$ii] & @CRLF & @CRLF ContinueLoop 2 EndIf Next Else $sErrorLog &= 'Missing Video Stream:' & @CRLF & $aAllFiles[$ii] & @CRLF & @CRLF ContinueLoop EndIf ; Find Audio Streams $aFindAudioStreams = _ArrayFindAll( $aAllStreams , 'codec_type=audio' , 0 , 0 , 0 , 1 ) If $aFindAudioStreams <> -1 Then ; Process Audio Streams For $aa = 0 To UBound( $aFindAudioStreams ) - 1 $sSAudioCodec = _RegExString( $aAllStreams[$aFindAudioStreams[$aa]] , '(?s)(?i)(?:.+?codec_name=(\S+))?' ) $iSAudioChannels = _RegExString( $aAllStreams[$aFindAudioStreams[$aa]] , '(?s)(?i)(?:.+?channels=(\S+))?' ) If $sSAudioCodec <> 'AAC' And $sSAudioCodec <> 'AC3' Then $sErrorLog &= 'Unsupported Audio Codec: (' & $sSAudioCodec & ')' & @CRLF & $aAllFiles[$ii] & @CRLF & @CRLF ContinueLoop 2 EndIf If $sSAudioCodec = 'AAC' And $iSAudioChannels > 2 Then $sErrorLog &= 'To Many Audio Channels: (' & $iSAudioChannels & ')' & @CRLF & $aAllFiles[$ii] & @CRLF & @CRLF ContinueLoop 2 EndIf Next Else $sErrorLog &= 'Missing Audio Stream:' & @CRLF & $aAllFiles[$ii] & @CRLF & @CRLF ContinueLoop EndIf EndIf Next ; Create Error Log If StringLen( $sErrorLog ) > 1 Then If NOT FileExists( @ScriptDir & '\Error Logs\' ) Then DirCreate( @ScriptDir & '\Error Logs\' ) $sErrorLogFile = @ScriptDir & '\Error Logs\[' & @YEAR & '-' & @MON & '-' & @MDAY & '] ' & @HOUR & '-' & @MIN & '-' & @SEC & '.txt' FileWrite( $sErrorLogFile , $sErrorLog ) ShellExecute( $sErrorLogFile ) EndIf ; Create Unknown File Extensions Text If $aUnknown > 0 Then $sUknownExtensions = @ScriptDir & '\UnKnown.txt' If FileExists( $sUknownExtensions ) Then Dim $aPriorUnknown _FileReadToArray( $sUknownExtensions , $aPriorUnknown ) For $ii = 1 To $aPriorUnknown $iFind2 = _ArraySearch( $aUnknown , $aPriorUnknown[$ii] , 1 ) If @Error Then _ArrayAdd( $aUnknown , $aPriorUnknown[$ii] ) $aUnknown += 1 EndIf Next FileDelete( $sUknownExtensions ) EndIf _FileWriteFromArray( $sUknownExtensions , $aUnknown , 1 ) ShellExecute( $sUknownExtensions ) EndIf MsgBox( 0 , 'Finished' , 'Batch Operation Complete' ) Func _Macros( $sFile ) Global $sFileDir = StringLeft ( $sFile , StringInStr( $sFile , '\' , 0 , -1 ) ) Global $sFileExt = StringTrimLeft ( $sFile , StringInStr( $sFile , '.' , 0 , -1 ) - 1 ) Global $sFileName = StringTrimLeft ( $sFile , StringInStr( $sFile , '\' , 0 , -1 ) ) Global $sShortName = StringLeft ( $sFileName , StringInStr( $sFileName , '.' , 0 , -1 ) - 1 ) Global $sParent = StringLeft ( $sFileDir , StringInStr( $sFileDir , '\' , 0 , -2 ) ) Global $sFolderName = StringTrimRight( StringTrimLeft( $sFileDir , StringInStr( $sFileDir , '\' , 0 , -2 ) ) , 1 ) EndFunc Func _RandomString() $sString = '' Dim $aSpace For $i = 1 To 15 $aSpace = Chr( Random( 65 , 90 , 1 )) ; A-Z $aSpace = Chr( Random( 97 , 122 , 1 )) ; a-z $aSpace = Chr( Random( 48 , 57 , 1 )) ; 0-9 $sString &= $aSpace[Random( 0 , 2 , 1 )] Next Return $sString EndFunc Func _RegExString( $sString , $sRegEx ) Local $sValue = _ArrayToString( StringRegExp( $sString , $sRegEx , 1 )) If StringIsFloat( $sValue ) = 1 OR StringIsInt( $sValue ) = 1 Then Return Number( $sValue ) Else If $sValue = 'N/A' OR $sValue = 'N' OR $sValue = 'A' Then Return '' Else Return $sValue EndIf EndIf EndFunc
Now save the script & execute it by double clicking it and then select the folder holding your videos that you wish to process.
Now go do something else, this will take a while...maybe a great while depending on the number of videos you have.
The script will notify you when it's done...and if you're curious as to if it's still running there should be a icon in your system tray that looks like a blue "A". Past that you can start your Task Manager and you should more than likely see FFMpeg running in the background.
This should possibly produce one or more text files.
The primary one will be what is produced in the "Error Logs" folder, this will list what files failed and why...but keep in mind these only list the first reason why it failed, not all possible reasons it may have failed. A number of these may not even be video files at all...but a format that should have been excluded from the search.
Which brings me to the next file "UnKnown.txt" this file will be updated with one instance per unknown file extension, possibly every time you run the script and it finds something new.
Now ideally I have all or at least most common non video extensions excluded from the search...this is everything on the right side of the pipe "|" symbol on line 21 at present.
You may wish to add new extensions to be excluded from future searches...thus speeding the script along...but please consider sharing your additional excludes here in this thread, to help others out as well.
You may wish to use one of my app's, called VideoGain (free) to process the failed video files. It's main purpose is to batch adjust audio volume, so that all the videos have more or less the same gain...so you don't have to monkey around with your volume all the time.
Originally it only processed folders full of videos...not individual, but since I was already making some corrections to it already...I set it up to do single files as well.
Here is where we get hackish.
Download VideoGain & extract it somewhere...ideally in a folder called VideoGain so it's easier to find later on. Now Start it by double clicking on it's exe...then close the app...it will now have produced a new INI file...and we are going to edit it's contents with whatever your favorite text editor happens to be (Notepad, Notepad++, UltraEdit,..).
In the VideoGain.ini all the way at the bottom...you should see an entry called "[Folders]".
Now below that we'll be adding entries of our own...basically copy and paste from your Error Logs...into this file...but before each path put "Folder_#=" replacing the # with a number value...please keep each value different, and each entry on a new line.
I'll likely write a simple script to help in this matter tomorrow.
Anyways once all the edits are made...save the file, and restart VideoGain.
You should now see all the files you want to process listed on the "Folders" tab.
Now check "Direct Replace" and uncheck "Recurse Folders" (not needed).
Now click on the "Settings" tab.
If you had any videos that failed because they were not H264 then set the Encoder to "Conditional" which basically means if VideoGain doesn't detect the video stream to be H264..to then encode..but only then. Make further adjustments as you like to the H264 settings and Video settings.
Now if you had Audio errors, you have a few picks...you can go with AAC or AC3...encoders...with the covet that AAC is limited to stereo. Right now if you select AC3...all videos will have the audio track re-encoded, bar non...I don't have an early out for that right now as I just added AC3 support...however if you select AAC and a number of your tracks are already AAC...and those tracks are Stereo...then you can select "ReplayGain (Tags)" this will do a non damaging adjustment to the AAC tracks...however all non AAC tracks will be encoded to AAC.
Select "Stereo DownMix" if you plan to use AAC.
All resulting files will ether be Mp4 or Mkv depending on what you selected for a container, from the drop down at the bottom of the application.
Press "Start" and away you go.
I would personally suggest doing at little processing as you need to. Each time something gets encoded...it gets more damaged.
Edited by Nologic, 18 April 2015 - 02:28 AM.