Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
|
|
Thread Tools | Search this Thread | Display Modes |
9th October 2017, 18:14 | #1 | Link |
Broadcast Encoder
Join Date: Nov 2013
Location: Royal Borough of Kensington & Chelsea, UK
Posts: 2,869
|
Automatic Video Analyzer (luma values, chroma values etc)
Hi,
I'm looking for an Automatic Video Analyzer, which analyses both video and audio of an encoded file and gives me results: whether luma and chroma are out of range (Tv Range) or not, whether the audio loudness is too high or not (-24LUFS is the broadcast standard), whether there are many dialogues or not (mainly music for instance), and finally if there are many still footages or if it's dynamic. I've been using Cerify (provided by Tektronix) so far, but it seems it doesn't quite do what I want. (it partially does it). The main reason why I'm asking this, is not to test encoded files to see whether they are within the standard or not, but to divide them into categories. For instance, if a movie is shot during the night, for instance, I'm gonna have a very low luma (with lots of black scenes). On the other hand, if a movie is mainly shot outside during the day, luma value is gonna be high. That's what I'm interested in, 'cause it falls into automation and that's what marketing asked me. But... I'm an encoder, so I don't know how to get these values automatically unless I manually spot-check the movie with a videoscope (I obviously can't do that). Any thoughts? Is there a way to get these values (according to personalized thresholds, perhaps)? Thank you in advance. Last edited by FranceBB; 9th October 2017 at 18:17. |
9th October 2017, 19:59 | #2 | Link |
Registered User
Join Date: Dec 2005
Location: Germany
Posts: 1,795
|
__________________
AVSRepoGUI // VSRepoGUI - Package Manager for AviSynth // VapourSynth VapourSynth Portable FATPACK || VapourSynth Database |
10th October 2017, 00:28 | #3 | Link | |
Retried Guesser
Join Date: Jun 2012
Posts: 1,373
|
Quote:
...seems like a good way to communicate the general look and feel of a film in a way that marketing guys can understand. (the multicolored bar grows from left to right as the video plays) https://forum.doom9.org/showthread.php?t=167769 https://forum.doom9.org/showthread.p...69#post1799769 Code:
################################## # Trailer Fingerprint: How? Is it even possible? # http://forum.doom9.org/showthread.php?t=167769 ## http://forum.doom9.org/showthread.php?p=1626707#post1626707 ## (note: long load time) ## function fingerprint_1(clip src, int "fingerprint_height") { fph = Default(fingerprint_height, 32) w = Width(src) v = Crop(src, 8, 8, -8, -8) v = BicubicResize(v, 640, 360) calc = FrameRate(v) * w / Framecount(v) v = ChangeFPS(v, calc, linear = false).Trim(0, -w) v = ConvertToRGB32(v).BicubicResize(4, 4).Blur(0.65).BilinearResize(2, 2) a = Crop(v, 0, 0, -1, -1) b = Crop(v, 1, 0, 0, -1) c = Crop(v, 0, 1, -1, 0) d = Crop(v, 1, 1, 0, 0) x = Overlay(a, b, mode="blend", opacity=0.5) y = Overlay(c, d, mode="blend", opacity=0.5) v = Overlay(x, y, mode="blend", opacity=0.5) v = PointResize(v, 1, fph) v = WeaveColumns(v, w).Converttoyv12() bg = BlankClip(Width=w, Height=fph) v = StackVertical(src, v) Function ovl(clip c1, clip c2, int xx, int yy) { \ Overlay(c1, c2 , xx , yy) \ } v = Animate(v, 0, src.framecount+1, "ovl", \ bg, 0, src.Height, \ bg, src.Width, src.Height) return v } |
|
10th October 2017, 00:54 | #4 | Link |
Broadcast Encoder
Join Date: Nov 2013
Location: Royal Borough of Kensington & Chelsea, UK
Posts: 2,869
|
@raffriff42... thanks! Well, it kinda is. I also started implementing something kinda nice that I think they'll use.
It basically gets the average luma value of each frame through avisynth, writes every value to a text file and then a program in C# reads these values, and uses these values to get the average value of the whole movie, then checks whether it's within a certain threshold and outputs a result: 1) "The average value is xxx, this movie develops during the night" 2) "The average value is xxx, this movie has some dark/night scenes" 3) "The average value is xxx, this movie has some bright/morning scenes" 4) "The average value is xxx, this movie develops during the daylight" Avisynth Script: Code:
FFVideoSource("test.mxf") PointResizeMT(704, 396) ScriptClip(Last, """ threshold = 55 luma = AverageLuma ## gives the average luma of the current frame #luma = AverageLuma(1) ## gives the average luma of the next frame luma < threshold \ ? Levels(0, 1.0+0.5*(threshold-luma)/threshold, 255, 0, 255) \ : last Subtitle("luma=" + String(luma), align=2) filename = "C:\Documents and Settings\l\Desktop\luma.txt" WriteFile(filename, "luma") """) Code:
using System; using System.Collections.Generic; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data.Common; using System.IO; namespace VideoAnalyzer { public partial class Form1 : Form { public Form1() { InitializeComponent(); button1.Click += button1_Click; button2.Click += button2_Click; button3.Click += button3_Click; } private void Form1_Load(object sender, EventArgs e) { } public void button1_Click(object sender, EventArgs e) { string text = File.ReadAllText(@"c:\VideoAnalyzer\NomeFile.ini", Encoding.UTF8); System.Diagnostics.Process.Start("explorer.exe", @text); } public void button2_Click(object sender, EventArgs e) { System.Diagnostics.Process.Start("explorer.exe", @"c:\VideoAnalyzer\processer.bat"); } private void button3_Click(object sender, EventArgs e) { //string text = File.ReadAllText(@"c:\VideoAnalyzer\luma.txt", Encoding.UTF8); string[] text = System.IO.File.ReadAllLines(@"c:\VideoAnalyzer\luma.txt", Encoding.UTF8); //int[] values = text.Select((l) => int.Parse(l)).ToArray(); float[] values = text.Select((l) => float.Parse(l)).ToArray(); double average = values.Average(); float peak = values.Max(); string valoremedio = average.ToString(); if (average >= 0 && average <= 37) { MessageBox.Show("The average value is " + valoremedio + "\n" + "this movie develops during the night"); } if (average >= 38 && average <= 98) { MessageBox.Show("The average value is " + valoremedio + "\n" + "this movie has some dark/night scenes"); } if (average >= 99 && average <= 140) { MessageBox.Show("The average value is " + valoremedio + "\n" + "this movie has some bright/morning scenes"); } if (average >= 141 && average <= 255) { MessageBox.Show("The average value is " + valoremedio + "\n" + "this movie develops during the daylight"); } //MessageBox.Show(peak); /* string[] entries = Directory.GetFileSystemEntries(text, "*", SearchOption.AllDirectories); foreach (string value in entries) { string numeroluma = Path.GetFileNameWithoutExtension(value); ListViewItem item = new ListViewItem(numeroluma); } */ } } } |
10th October 2017, 03:42 | #5 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
ShowChannels, http://forum.doom9.org/showthread.php?t=163829
Code:
ShowChannels() (c) 2012 StainlessS Plugins for Avisynth v2.5 & v2.6 Planar, YUY2 and RGB. Simple plugin whose only function is to display the average Y,U and V values for a YUV frame or R,G, and B for an RGB frame. Also shows accumulated average for all frames visited so far. Typical output for a YUV clip:- --------------------------- 347 ] Frames Visited = 348 This Frame Accumulated Y U V Y U V Ave 77.00 125.52 125.42 70.91 125.87 125.78 Min 4 80 95 0 69 83 Max 255 177 165 255 190 174 ~Min 14 95 101 12 92 101 ~Max 234 167 148 235 167 151 --------------------------- where 'AVE' shows average for current frame and accumulated average for all visited frames. 'MIN' shows minimum value for a channel, this frame and accumulated. 'MAX' shows maximum value for a channel, this frame and accumulated. '~MIN' shows loose minimum value for a channel, this frame and accumulated. '~MAX' shows loose maximum value for a channel, this frame and accumulated. Loose minimum uses the filter arg float MinPerc, a percentage of total pixels to ignore when finding the loose minimum, allows to ignore extreme stray pixels (noise). Loose maximum uses the filter arg float MaxPerc, a percentage of total pixels to ignore when finding the loose maximum, allows to ignore extreme stray pixels (noise). The "loose" values are made to filter out very bright or very dark noise creating an artificially low or high minimum / maximum. The Accumulated Ave is a "Average of Averages", or "Average Mean" or "Mean Average", take your pick but accumulated seemed more appropriate considering that it was not restricted to describing just the averages. Accumulated Min is the minimum of all minimums so far, etc. Usage:- ShowChannels(clip c,float "MinPerc"=0.1, float "MaxPerc"=0.1, bool "ver"=false,bool "Setvar"=false,String "Prefix"="SC_", \ bool "Show"=true,String ="AccFile"="",int "x"=0,int "y"=0,int "w"=0,int "h"=0,bool "Interlaced"=false) Where:- c is the clip MinPerc is percentage of pixels to ignore for loose minimum. (default 0.1%, ie 1/1000 of total pixels) ColorYUV (Analyze=true) Loose Minimum ignores 1/256 of the darkest pixels, and ShowChannels 0.1% or 1/1000 by default, so a Minperc of 0.4% would be about the same as ColorYUV uses. MaxPerc is percentage of pixels to ignore for loose maximum. (default 0.1%, ie 1/1000 of total pixels) ColorYUV (Analyze=true) Loose Maximum ignores 1/256 of the lightest pixels, and ShowChannels 0.1% or 1/1000 by default, so a Maxperc of 0.4% would be about the same as ColorYUV uses. ver display version info, false OFF [default] , true ON Setvar if true then sets Global Variables using Prefix string. Prefix (default "SC_"), prefix to Global variable names when using SetVar. Show, false switches off normal text display, you may want to set false if using SetVar. AccFile, default "", name of text file to output final Accumulated values for entire file. x,y,w,h, sets coordinates, all default to 0 as for crop, ie full image. NOT colorspace limited, eg can use odd values even for YV12 and YUY2. Interlaced (default false). Planar formats only, alters interpretation for the chroma, false=Progressive, true=interlaced. Default Global variable names when SetVar=true and using Default Prefix = "SC_" "SC_Visited" = Frames visited Channel 0 (Y or R) "SC_Ave_0","SC_Min_0","SC_Max_0","SC_LMn_0","SC_LMx_0","SC_AAve_0","SC_AMin_0","SC_AMax_0","SC_ALMn_0","SC_ALMx_0", Channel 1 (U or G, NOT Y8) "SC_Ave_1","SC_Min_1","SC_Max_1","SC_LMn_1","SC_LMx_1","SC_AAve_1","SC_AMin_1","SC_AMax_1","SC_ALMn_1","SC_ALMx_1", Channel 2 (V or B, NOT Y8) "SC_Ave_2","SC_Min_2","SC_Max_2","SC_LMn_2","SC_LMx_2","SC_AAve_2","SC_AMin_2","SC_AMax_2","SC_ALMn_2","SC_ALMx_2", For Y8, channels 1 and 2 will all be set to -1 -------------------------------------------------------------------------------- Typical Global Variable settings for RGB something like:- SC_Ave_0=124.55 SC_Ave_1=126.06 SC_Ave_2=199.77 SC_Min_0=0 SC_Min_1=0 SC_Min_2=0 SC_Max_0=255 SC_Max_1=255 SC_Max_2=255 SC_LMn_0=0 SC_LMn_1=0 SC_LMn_2=0 SC_LMx_0=255 SC_LMx_1=255 SC_LMx_2=255 SC_AAve_0=129.24 SC_AAve_1=132.12 SC_AAve_2=126.68 SC_AMin_0=0 SC_AMin_1=0 SC_AMin_2=0 SC_AMax_0=255 SC_AMax_1=255 SC_AMax_2=255 SC_ALMn_0=0 SC_ALMn_1=0 SC_ALMn_2=0 SC_ALMx_0=255 SC_ALMx_1=255 SC_ALMx_2=255 -------------------------------------------------------------------------------- Contents of AccFile for a small sample clip showing typical output using defaults: SC_AAve_0=98.971779 SC_AMin_0=0 SC_AMax_0=255 SC_ALMn_0=14 SC_ALMx_0=241 SC_AAve_1=122.572746 SC_AMin_1=66 SC_AMax_1=200 SC_ALMn_1=99 SC_ALMx_1=160 SC_AAve_2=137.286911 SC_AMin_2=72 SC_AMax_2=209 SC_ALMn_2=108 SC_ALMx_2=175 SC_Visited=4000 -------------------------------------------------------------------------------- Lastly, you may find it better to crop off any borders when ascertaining frame/accumulated values, or set coordinates to suit. ssS EDIT: Also ClipBlend(delay=0):- http://forum.doom9.org/showthread.php?t=168048 Code:
ClipBlend(clip,"delay"=0) # 8 bit Planar, YUY2, RGB ClipBlend16(clip,"delay"=0) # 16 bit, Stack16 Planar, YUY2, RGB (see Dither Tools) Added Delay arg to plugin. Delay, default = 0, == ALL frames played so far blended. 1 = blend with previous frame ie two frames blended. 10 = blend with 10 previous frames, ie 11 frames blended, etc. Accumulator resets at frame 0. To get average of all frames 0 to frame 300 # ------------------------ FRM =300 # Required frame number Avisource("D:\avs\test.avi") ClipBlend() # Default delay=0 ie all previous frames Trim(FRM,-1) # Get Required frame return Last # ------------------------ Or to get a single frame average of all frames in a clip # ------------------------ Avisource("D:\avs\test.avi") ClipBlend() return Trim(FrameCount-1,-1) # ------------------------ How ClipBlend it works ClipBlend() uses a single 32 bit accumulator (unsigned int) for each channel of each pixel x,y position in the clip frame. With a maximum possible value per pixel/channel being 255 ie 8 bits, this leaves 24 bits available for accumulating the sum of values for that pixel/channel position, ie adding the values for that pixel/channel from every selected frame in the blended range. The additional 24 bits would allow for up to ~16 Million (2^24) frames to be summed, however we also need another bit to maintain maximum precision possible for 8 bit result, so reducing maximum possible frame range to ~8 million frames. Code: Return Avisource("test.avi").ClipBlend(delay=0).Trim(999,-1) # 1000 frames, 1000 values per accumulator, ie max 1000*255 Above would sum (each channel/pixel) with maximum possible sum for an accumulator being 1000*255 (about 18 bits, 2^10=1024,2^8=256) As clipblend scans frames, it adds the channel/pixel values at each x,y position to the accumulators, for all of the required frames. If delay = 0, it just adds next frame values to the accumulators. If eg delay=10, and current scanned range is already 10, it subtracts the channel/pixel values of the oldest frame (lowest number) and then adds the values for the next frame to the accumulators. When delivering the result (delay=whatever), it just divides the accumulated sum by the number of sample frames to get the average, and writes it to the relevant pixel/channel/x/y position, could not be simpler. Implementation is equivalent to this: int(accumulator / Float(FramesDone) + 0.5) The actual implementation and reason for the extra needed bit that was mentioned (ie accumulator*2): ((accumulator*2) + FramesDone) / (FramesDone*2) The *2 pair and addition of FramesDone is the integer equivalent of division, adding 0.5 and taking Int() whist maintaining max possible precision at 8 bits result.
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 10th October 2017 at 14:34. |
10th October 2017, 22:40 | #6 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
A Different take, dont know if of any use at all.
SequenceAverage.avs (if separate scripts, need Import) Code:
/* SequenceAverage.avs Returns a clip of n sequences, where every frame in each sequence is average color of all frames in source clip sequence. Req:- GScript, Grunt, (c) Gavino. RT_Stats v1.43, ClipBlend, CallCmd(if Auto Delete DB required), (c) StainlessS. */ GSCript(""" ###### DBase Field Numbers Global DB_IsVALID = 0 # Bool, true= Record Valid Global DB_START_FLD = 1 # Int, START frame field Global DB_END_FLD = 2 # Int, END frame Field Global DB_COLOR_FLD = 3 # Int, Color # DBase ID Index, basic clip validation. Global DB_IsYUV_ID = 0 # Int, 0=RGB : 1=YUV Global DB_FRMS_ID = 1 # Int, Framecount of input clip Global DB_WIDTH_ID = 2 # Int, Width of input clip Global DB_HEIGHT_ID = 3 # Int, Height of input clip Global DB_REC_ID = 4 # Int, Initialized Record Sequences # User Attributes, Debug On Frame and to Debugview Global DB_DBUG_ATTR = 0 # Int, 1 = DEBUG # User String Attributes Index Global DB_NAME_STR = 0 # String, Optional clip name for whatever use. ###### Function PrepDBase(clip c,String DB,Int Records,String "ClipName",Bool "Debug",Bool "PreScan") { # Initialize DBase, Optional PreScan myName="PrepDBase: " Debug = Default(Debug,False) PreScan = Default(PreScan,False) # If True, then force Prescan producing Valid DBase on function exit, Function returns PreScan Status. Assert(DB!="",RT_String("%sNeed DBase name",myName)) Frms = c.FrameCount Assert(0 < Records <= Frms,RT_String("%s0 < Records(%d) <= c.FrameCount(%d)",myName,Records,Frms)) (Debug) ? RT_DebugF("Allocating DBase of %d Sequences/Records for %d frame clip",Records,Frms,name=myName) : NOP RT_DBaseAlloc(DB,Records,"biii") # Bool, Int, Int, Int MaxFramesPerRecord = Ceil(Float(Frms) / Records) (Debug) ? RT_DebugF("MaxFramesPerRecord =%d",MaxFramesPerRecord,name=myName) : NOP E=-1 for(rec=0,Records-1) { S = E + 1 E = Min(S + MaxFramesPerRecord,Frms) - 1 RT_DBaseSetField(DB,rec,DB_START_FLD,S) RT_DBaseSetField(DB,rec,DB_END_FLD, E) (DEBUG) ? RT_DebugF("%d} [%d,%d] (%d Frames)",rec,S,E,E-S+1,Name=myName) : NOP } RT_DBaseSetID(DB,DB_IsYUV_ID, c.IsRGB?0:1) RT_DBaseSetID(DB,DB_FRMS_ID, c.FrameCount) RT_DBaseSetID(DB,DB_WIDTH_ID, c.Width) RT_DBaseSetID(DB,DB_HEIGHT_ID, c.Height) RT_DBaseSetID(DB,DB_REC_ID, Records) # Number of records that are properley initialized. ClipName=Default(ClipName,"") # Optional clip name to store in user strings RT_DBaseSetStrAttrib(DB,DB_NAME_STR,ClipName) # Set Clipname RT_DBaseSetAttrib(DB,DB_DBUG_ATTR,Debug?1:0) # Set DEBUG Status if(PreScan) {for(rec=0,Records-1) {DBaseSetSeqColor(c,DB,rec)}} # PreScan, so the DBase is fully valid before function exit. return PreScan # Returns PreScan Status } Function DB_FindTrim(String DB,Int S_Field,Int E_Field,Int Frame) { # DB_FindTrim Returns clip (or record number) containing movie frame Frame. # NOTE, This script function replaced in RT_Stats v2.0, by plugin version RT_DBaseFindSeq(). result = -1 # Init NOT FOUND low = 0 high = RT_DBaseRecords(DB) - 1 while(low <= high) { mid = (low + high) / 2 if(RT_DBaseGetField(DB,mid,E_Field) < Frame) { low = mid + 1 } Else If (RT_DBaseGetField(DB,mid,S_Field) > Frame) {high = mid - 1 } Else {low = high + 1 Result = mid } } return result } Function DBaseClipCheck(clip c, String DB,String "OptNam") { # Basic check c corresponds with DBase clip OptNam=Default(OptNam,"") myName="DBaseClipCheck:"+(OptNam!=""?":"+OptNam:" ") if(RT_DBaseGetID(DB,DB_IsYUV_ID)!=(c.IsRGB?0:1)) {S=RT_String("%sDB_IsYUV_ID Invalid for clip",myName) RT_DebugF("%s",S) Assert(false,S)} if(RT_DBaseGetID(DB,DB_FRMS_ID)!=c.FrameCount) {S=RT_String("%sDB_FRMS_ID Invalid for clip",myName) RT_DebugF("%s",S) Assert(false,S)} if(RT_DBaseGetID(DB,DB_WIDTH_ID)!=c.Width) {S=RT_String("%sDB_WIDTH_ID Invalid for clip",myName) RT_DebugF("%s",S) Assert(false,S)} if(RT_DBaseGetID(DB,DB_HEIGHT_ID)!=c.Height) {S=RT_String("%sDB_HEIGHT_ID Invalid for clip",myName) RT_DebugF("%s",S) Assert(false,S)} if(RT_DBaseGetID(DB,DB_REC_ID)!=RT_DBaseRecords(DB)) {S=RT_String("%sDB_REC_ID Invalid",myName) RT_DebugF("%s",S) Assert(false,S)} return True } Function DBaseSetSeqColor(clip c, String DB,Int rec) { # Set Averge color for seqence/record myName="DBaseSetSeqColor: " Records = RT_DBaseRecords(DB) if(!(0 <= rec < Records)) {S=RT_String("%s0 <= rec(%d) < Records(%d)",myName,rec,Records) RT_DebugF("%s",S) Assert(false,S)} DBaseClipCheck(c,DB,myName) IsValid = RT_DBaseGetField(DB,rec,DB_IsVALID) # Have we used Clipblend on this range yet ? if(!IsValid) { Start_Frm = RT_DBaseGetField(DB,rec,DB_START_FLD) End_Frm = RT_DBaseGetField(DB,rec,DB_END_FLD) DBUG = (RT_DBaseGetAttrib(DB,DB_DBUG_ATTR) != 0) # (DBUG) ? RT_DebugF("%d} [%d,%d] Getting sequence color",rec,Start_Frm,End_Frm,name=myName) : NOP nFrames = End_Frm - Start_Frm + 1 # Avoid End_Frm==0 prob. Tmp_C = c.Trim(Start_Frm,-nFrames) Tmp_C = Tmp_C.ClipBlend(Delay=0).Trim(nFrames-1,-1) # Average entire range, quick nchans = Tmp_C.RT_ChanAve(n=0) # Get chan averages as locals (will be integer floats) ch0=Int(RCA_Ave_0) ch1=Int((nchans!=1)?RCA_Ave_1:128) ch2=Int((nchans!=1)?RCA_Ave_2:128) Col=(ch0*256+ch1)*256+ch2 RT_DBaseSetField(DB,rec,DB_COLOR_FLD,Col) # Y8 Set as $XX8080 RT_DBaseSetField(DB,rec,DB_IsVALID,True) # Now Valid (DBUG) ? RT_DebugF("%d} [%d,%d] Setting sequence color=$%0.6X",rec,Start_Frm,End_Frm,Col,name=myName) : NOP } return True } Function GetAveColor(clip c, String DB, Int Frm) { # Find Average Color of Frame, returning Int myName="AveColor: " rec=DB_FindTrim(DB,DB_START_FLD,DB_END_FLD,Frm) if(!(rec>=0)) {S=RT_String("%sDB_FindTrim could not find record for frame %d",myName,Frm) RT_DebugF("%s",S) Assert(false,S)} IsValid = RT_DBaseGetField(DB,rec,DB_IsVALID) # Have we used ClipBlend on this range yet ? (!IsValid) ? DBaseSetSeqColor(c,DB,rec) : NOP # Set Dbase for current sequence/record col = RT_DBaseGetField(DB,rec,DB_COLOR_FLD) return Col } Function GetAveColorFrame(clip c, String DB, Int Frm) { # Return frame, that is Average color of its record/sequence (Same frame type/size as clip c) col = GetAveColor(c,DB,Frm) (c.IsRGB) ? c.BlankClip(Length=1,color=col) : c.BlankClip(Length=1,color_yuv=col) DBUG = (RT_DBaseGetAttrib(DB,DB_DBUG_ATTR) != 0) # DBUG Status (DBUG) \ ? RT_Subtitle("%d/%d] Seq=%d/%d Col=$%0.6X\n'%s'", \ Frm,c.FrameCount-1,DB_FindTrim(DB,DB_START_FLD,DB_END_FLD,Frm),RT_DBaseRecords(DB)-1,col,RT_DBaseGetStrAttrib(DB,DB_NAME_STR)) \ : NOP return Last } Function ShortSequenceClip(clip c, String DB,Bool "Debug") { # Return clip with Single Frame Average for each Sequence (no audio). myName="ShortSequenceClip:" Debug=Default(Debug,False) # Function Specific Debug DBaseClipCheck(c,DB,myName) # Check DB OK Records=RT_DBaseRecords(DB) cret=c.BlankClip(Length=0) for(rec=0,records-1) { (!RT_DBaseGetField(DB,rec,DB_IsVALID)) ? DBaseSetSeqColor(c,DB,rec) : NOP # Scan if Necessary Start_Frm = RT_DBaseGetField(DB,rec,DB_START_FLD) # start frame of this sequence End_Frm = RT_DBaseGetField(DB,rec,DB_END_FLD) # end frame of this sequence col = GetAveColor(c,DB,Start_Frm) # Average color of the sequence (c.IsRGB) ? c.BlankClip(Length=1,color=col) : c.BlankClip(Length=1,color_yuv=col) (DEBUG) \ ? RT_Subtitle("ShortSeq:\n%d/%d} S=%d E=%d Len=%d Col=$%0.6X\n'%s'", \ rec,Records-1,Start_Frm,End_Frm,End_Frm-Start_Frm+1,col,RT_DBaseGetStrAttrib(DB,DB_NAME_STR)) \ : NOP cret = cret ++ Last # Add to Clip so far/ } return cret.KillAudio } """) Code:
# Client Script, Several Demo uses rolled into one. #Import("SequenceAverage.avs") ##### CONFIG ##### FileName = "D:\TEST.AVI" DB = "MyDBase.DB" # DBase Name OUTLOG = "MyLog.Log" # Demo Log SEQUENCES = 25 # Average clip into SEQUENCES number of sequences DEBUG = True # Some Debug Stuff PRESCAN = False # Whether or not to scan and fully prep DBase prior to clip play. (Better if True) SHORTSEQ = False # If True then generate only single frame for each sequences, else use Scriptclip DEL_DB = False # Delete DBase on clip closure, Requires CallCmd if True ### End CONFIG ### FileName = (FileName!="") ? RT_GetFullPathName(FileName) : FileName DB = (DB!="") ? RT_GetFullPathName(DB) : DB # Make sure is full filename incl Drive and path nodes OUTLOG = (OUTLOG!="") ? RT_GetFullPathName(OUTLOG) : OUTLOG Assert(FileName!="","Need FileName") Assert(DB!="","Need DB") ######################## AVISource(FileName) Trim(0,-1000) # 1000 Frame test clip #BiCubicResize(640,480) # Whatever PrepDBase(DB,SEQUENCES,ClipName=FileName,Debug=DEBUG,PreScan=PRESCAN) # Prepare DB GScript(""" # Demo usage to access Fully PreScanned DBase, for whatever reason if(PRESCAN && OUTLOG !="") { RT_FileDelete(OUTLOG) # Del Existing, log file RT_WriteFile(OUTLOG,"FileName='%s'",FileName,Append=True) RT_WriteFile(OUTLOG,"DB ='%s'",DB,Append=True) RT_WriteFile(OUTLOG,"SEQS = %d", SEQUENCES,Append=True) RT_WriteFile(OUTLOG,"IsYUV = %s", RT_DBaseGetID(DB,DB_IsYUV_ID)!=0,Append=True) # Bool is printed as a String RT_WriteFile(OUTLOG,"FrmCnt = %d", RT_DBaseGetID(DB,DB_FRMS_ID),Append=True) RT_WriteFile(OUTLOG,"Width = %d", RT_DBaseGetID(DB,DB_WIDTH_ID),Append=True) RT_WriteFile(OUTLOG,"Height = %d", RT_DBaseGetID(DB,DB_HEIGHT_ID),Append=True) RT_WriteFile(OUTLOG,"Records = %d", RT_DBaseRecords(DB),Append=True) # Same As SEQUENCES RT_WriteFile(OUTLOG,"ClipName='%s'",RT_DBaseGetStrAttrib(DB,DB_NAME_STR),Append=True) # Internally stored DBase clip name RT_WriteFile(OUTLOG,"DEBUG = %d", RT_DBaseGetAttrib(DB,DB_DBUG_ATTR),Append=True) # Internally stored Debug, 0=False, 1=True RT_WriteFile(OUTLOG,"\n",Append=True) # Blank Line for(i=0,SEQUENCES-1) { RT_WriteFile(OUTLOG,"%d} [%d,%d:Len=%d] Color=$%0.6X", \ i, \ RT_DBaseGetField(DB,i,DB_START_FLD), \ RT_DBaseGetField(DB,i,DB_END_FLD), \ RT_DBaseGetField(DB,i,DB_END_FLD)-RT_DBaseGetField(DB,i,DB_START_FLD)+1, \ RT_DBaseGetField(DB,i,DB_COLOR_FLD), \ Append=True) } } """) SCRIPT = """return GetAveColorFrame(DB,current_frame)""" # For ScriptClip mode only : Not used for SHORTSEQ (SHORTSEQ) \ ? Last.ShortSequenceClip(DB,DEBUG) \ : Last.Scriptclip(SCRIPT,args="DB",Local=True) (DEL_DB) ? CallCmd(Close="CMD /C del "+DB, Hide=true) : NOP Return Last above splits clip into n sequences of same number of frames each (perhaps fewer in last sequence). NOTE, in Scriptclip mode, will auto scan each new sequence on frame access that has not as yet been sequence scanned, so may pause at each sequence, or can call PrepDBase(PreScan=true) to prescan complete clip before commence play clip.
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 10th October 2017 at 23:19. |
10th October 2017, 22:47 | #7 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
OutLog.log for above posted script
Show for each sequence, start frame, end frame, len of seq, Average color of sequence. Code:
FileName='D:\TEST.AVI' DB ='D:\MyDBase.DB' SEQS = 25 IsYUV = True FrmCnt = 1000 Width = 1280 Height = 604 Records = 25 # Same as SEQS (DB Internal) ClipName='D:\TEST.AVI' # Same as FileName (DB Internal) DEBUG = 1 0} [0,39:Len=40] Color=$2A887B 1} [40,79:Len=40] Color=$308C79 2} [80,119:Len=40] Color=$308C7A 3} [120,159:Len=40] Color=$31897C 4} [160,199:Len=40] Color=$3F8D7A 5} [200,239:Len=40] Color=$368E77 6} [240,279:Len=40] Color=$338C79 7} [280,319:Len=40] Color=$5C9070 8} [320,359:Len=40] Color=$338879 9} [360,399:Len=40] Color=$3A8779 10} [400,439:Len=40] Color=$3B867A 11} [440,479:Len=40] Color=$36867A 12} [480,519:Len=40] Color=$3E8A76 13} [520,559:Len=40] Color=$338978 14} [560,599:Len=40] Color=$40847B 15} [600,639:Len=40] Color=$378B77 16} [640,679:Len=40] Color=$4F8A78 17} [680,719:Len=40] Color=$3A8977 18} [720,759:Len=40] Color=$498976 19} [760,799:Len=40] Color=$398977 20} [800,839:Len=40] Color=$328879 21} [840,879:Len=40] Color=$4A8279 22} [880,919:Len=40] Color=$3F7F7D 23} [920,959:Len=40] Color=$3F7A83 24} [960,999:Len=40] Color=$427D81
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 10th October 2017 at 23:12. |
11th October 2017, 09:31 | #8 | Link |
Registered User
Join Date: Mar 2006
Posts: 1,049
|
https://www.ffmpeg.org/ffmpeg-filter...#signalstats-1
https://www.ffmpeg.org/ffmpeg-filters.html#loudnorm https://www.ffmpeg.org/ffmpeg-filters.html#astats-1 https://www.ffmpeg.org/ffmpeg-filters.html#ebur128-1 Last edited by pandy; 11th October 2017 at 09:36. |
Thread Tools | Search this Thread |
Display Modes | |
|
|