Setting markers to the beat via script?

Get answers to your questions about color grading, editing and finishing with DaVinci Resolve.
  • Author
  • Message
Offline

brokenfeet

  • Posts: 18
  • Joined: Wed Sep 25, 2019 10:25 am
  • Real Name: Volker Klink

Setting markers to the beat via script?

PostWed Jan 13, 2021 10:20 pm

Hi guys!
I would like to cut a video to a beat of a song.
Normally I play the song and set markers on the beats manually. (Transient detection doesn't work...its not a dance song :D )
This method normally works pretty fine but also you will get some "jitter" of a few frames just because i'm not a drummer with a perfect sense for rhythm.

Anyway...I know the tempo/bpm of the song. So my idea is:
Find a DEFINITE start of a measure (the kickdrum...) and set one marker. From that marker on, I want to set a series of markers, all 57 frames apart: because that's one measure at 105 bpm (the song) at 25 fps.

Assuming that the song does not have any tempo changes, this should generate a marker on each "One" of the song.
I guess this can be done with a LUA/python script pretty easily...but I haven't done that yet at all. (I know some programming though....)

Can anyone give me some starting tipps?

Thanks
Volker
Offline
User avatar

Igor Riđanović

  • Posts: 1040
  • Joined: Thu Jul 02, 2015 5:11 am
  • Location: Los Angeles, Calif.

Re: Setting markers to the beat via script?

PostThu Jan 14, 2021 4:54 am

Here is a script that will do it. I haven't tested it though.
Code: Select all
resolve = bmd.scriptapp('Resolve')
project = resolve.GetCurrentProject()
timeline = project.GetCurrentTimeline()

# Frame rate. You can also get the actual rate from GetSetting()
fps = 23.976

# BPM
bpm = 60

# Set offset for the starting marker
offset = 0

markerSpacing = 60*fps/bpm

# Place 100 timeline markers. You can also calculate the marker count
# from the timeline length and the markerSpacing
for i in range(0 + offset, 100, round(markerSpacing)):
    timeline.AddMarker(i, 'blue', 'My beats', 'My note', 1)

These two tutorials are kind of old, but the fundamentals haven't changed a lot. I have a few other tutorials on scripting there.

www.metafide.com - DaVinci Resolve™ Apps
Offline

Peter Cave

  • Posts: 2523
  • Joined: Thu Aug 23, 2012 6:45 am
  • Location: Melbourne, Australia

Re: Setting markers to the beat via script?

PostThu Jan 14, 2021 8:54 am

If you don't want to use scripting you can make a 57 frame clip of a generator and copy/paste a block of 10 to 20 of them on a timeline for as long as you want. Then you can edit on video track 2 or step to each clip boundary and add a marker, using the down arrow and M key until you have the duration required. It's quite quick and faster than learning the scripting method. If you do this on a regular basis then scripting is worth spending the time to learn.
Resolve 16.2.6 AND Resolve 17.2
Mac OSX 10.14.6, Hackintosh i7 8700 32GB RAM, Radeon RX 580 8GB
Decklink Studio 2, FSI LM1770 Monitor
Offline

brokenfeet

  • Posts: 18
  • Joined: Wed Sep 25, 2019 10:25 am
  • Real Name: Volker Klink

Re: Setting markers to the beat via script?

PostThu Jan 14, 2021 9:17 am

Hi everyone!
Thanks so far!

Apparently I'm already struggling with getting Python to work or the environment variables.

So for example, if I run this command in the console of Davinci:

Py2> R = bmd.scriptapp('Resolve')
Py2> R
Py2> print R
Resolve (0x00007FF686A31CE0) [App: 'Resolve' on 127.0.0.1, UUID: 5eb9fc13-9fb3-4f31-868c-f39a577358fb]


There seems to be some pointer(?) to the Resolve interface(?).

But with the next command I get this:
p = resolve.GetCurrentProject()
Traceback (most recent call last):
File "<nofile>", line 1, in <module>
TypeError: 'NoneType' object is not callable


What am I missing here?
Offline

brokenfeet

  • Posts: 18
  • Joined: Wed Sep 25, 2019 10:25 am
  • Real Name: Volker Klink

Re: Setting markers to the beat via script?

PostThu Jan 14, 2021 9:20 am

Ah...also:
I know how to run the scripts via "Workspace-->Scripts"...but shouldn't it be possible to call the script from the console directly? How do I do that?

(Sorry for the noobie question...I'm used to Matlab, in which you also have an interpreter and a command line...but it seems a bit easier and intuitive).
Offline
User avatar

iddos-l

  • Posts: 515
  • Joined: Sat Mar 30, 2019 7:55 pm
  • Real Name: iddo lahman

Re: Setting markers to the beat via script?

PostThu Jan 14, 2021 7:24 pm

brokenfeet wrote:Hi everyone!
Thanks so far!

Apparently I'm already struggling with getting Python to work or the environment variables.

So for example, if I run this command in the console of Davinci:

Py2> R = bmd.scriptapp('Resolve')
Py2> R
Py2> print R
Resolve (0x00007FF686A31CE0) [App: 'Resolve' on 127.0.0.1, UUID: 5eb9fc13-9fb3-4f31-868c-f39a577358fb]


There seems to be some pointer(?) to the Resolve interface(?).

But with the next command I get this:
p = resolve.GetCurrentProject()
Traceback (most recent call last):
File "<nofile>", line 1, in <module>
TypeError: 'NoneType' object is not callable


What am I missing here?

In your example R is the resolve object so you should write:

p = R.ProjectManager().GetCurrentProject()
And so on...



Sent from my iPhone using Tapatalk
Offline
User avatar

iddos-l

  • Posts: 515
  • Joined: Sat Mar 30, 2019 7:55 pm
  • Real Name: iddo lahman

Re: Setting markers to the beat via script?

PostThu Jan 14, 2021 7:28 pm

brokenfeet wrote:Ah...also:
I know how to run the scripts via "Workspace-->Scripts"...but shouldn't it be possible to call the script from the console directly? How do I do that?

(Sorry for the noobie question...I'm used to Matlab, in which you also have an interpreter and a command line...but it seems a bit easier and intuitive).

I think this only works with studio.
In general you need to call python to execute the script. Depending on which python version you have or set in the env variables.
Something like:

Code: Select all
python3 your_script_path.py



Sent from my iPhone using Tapatalk
Offline

brokenfeet

  • Posts: 18
  • Joined: Wed Sep 25, 2019 10:25 am
  • Real Name: Volker Klink

Re: Setting markers to the beat via script?

PostThu Jan 14, 2021 8:57 pm

Hi guys!

Thanks for your support so far! I somehow managed to get Python 2 to work..

I actually made some progress...not perfectly the way I wanted it to be, but it might get the job done. I'll post the whole script on here later, if someone is interested.
I was wondering...on the one hand there seem to be some powerful scripting possibilites, on the other hand, something simple as "GetCurrentClip()" does not exist.

I was struggling with stuff like this:
Does not work: FirstClip.AddMarker(i, "red", "Marker1", "Marker1 at frame 1", 1)
Does work: FirstClip.AddMarker(i, "Red", "Marker1", "Marker1 at frame 1", 1)

But I can't find a documentation of those attributes/arguments anywhere :-(

Also in the Fusion script guide I couldn't find this...

Thanks!
Volker
Online

John Holt

  • Posts: 100
  • Joined: Sat Mar 02, 2019 8:54 pm
  • Real Name: John Holt

Re: Setting markers to the beat via script?

PostThu Jan 14, 2021 9:25 pm

Hello

This is now built into Version 17 with a little caveat, they have forgotten to finish it in the beta versions. I am hoping it will be included in the upcoming final release.

It is on the Fairlight tab and called transient detector.

Hope that helps
Stay Safe!
John
Offline
User avatar

Igor Riđanović

  • Posts: 1040
  • Joined: Thu Jul 02, 2015 5:11 am
  • Location: Los Angeles, Calif.

Re: Setting markers to the beat via script?

PostThu Jan 14, 2021 10:28 pm

brokenfeet wrote:...on the other hand, something simple as "GetCurrentClip()" does not exist.

I was struggling with stuff like this:
Does not work: FirstClip.AddMarker(i, "red", "Marker1", "Marker1 at frame 1", 1)
Does work: FirstClip.AddMarker(i, "Red", "Marker1", "Marker1 at frame 1", 1)

But I can't find a documentation of those attributes/arguments anywhere :-(

Also in the Fusion script guide I couldn't find this...


The concept of "current clip" doesn't really exist in a Resolve bin. By this do you mean the clip that's loaded in the source viewer? Or do you mean the clip or clips that are selected in the bin? Still the API does not provide access to either.

The documentation for valid marker color attributes does not exist. But you can get creative. One way to get it is by placing timeline markers of all colors, getting them via the API and examining the color name strings.

The Fusion scripting guide is included with Fusion 9. It's possible it's included with the newer standalone Fusion versions too.
www.metafide.com - DaVinci Resolve™ Apps
Offline

brokenfeet

  • Posts: 18
  • Joined: Wed Sep 25, 2019 10:25 am
  • Real Name: Volker Klink

Re: Setting markers to the beat via script?

PostThu Jan 14, 2021 11:39 pm

Hi everyone!

Thanks for your interest in this...
So..I've progressed a little bit more (and I now figured why I had trouble setting the markers to that first song in the first place...that song had a few breaks with measure changes in it....)

Anyway.
So my current script (will post it later, when beautified) does this:

- You set ONE marker on the first proper downbeat that you can find in your audio track
- run the script
- script will set a red marker according to the given bpm on each downbeat till the end of the audio clip.

bpm are still hard coded in the script but hoping to change that with a little GUI/User- dialog.
Also, I probably should add a dialogue to pick the audio track and so on. And the audio clip must be the first one within its track.

So, if the song is a typical pop or dance song, one can expect a very precise, steady rhythm and the script works pretty well.
I'll keep you updated soon!

Thx
Offline

brokenfeet

  • Posts: 18
  • Joined: Wed Sep 25, 2019 10:25 am
  • Real Name: Volker Klink

Re: Setting markers to the beat via script?

PostSat Jan 16, 2021 1:26 am

Hi everyone!

After spending WAY too much time on this I got this script now.
How it works:
1) Set the first few (reference) markers manually as precise as possible on the downbeats (at least two)
2) The markers must be "in a row" ---> don't skip a bar
3) run the script
4) it will estimate the BPM and set markers accordingly
5) check the console for some info

It works pretty well if you set the reference markers precisely... Problem is, the error of the "bpm estimation" adds up. So check the end of your audio clip....markers might be shifted there.
Currently works for the first audio clip on audio track #1.
I guess, the higher the framerate of the project, the better the result.
What do you think? I'm not really happy with it, probably going to "tap" a lot of my markers in the future anyway. It would be cool to combine this with the transient detection.

Here's the code (the init (importing....) of the script might be weird. I had no real idea what i was doing there....)
Code: Select all
from python_get_resolve import GetResolve
import DaVinciResolveScript
import sys
import math

resolve = GetResolve()
pm      = resolve.GetProjectManager()
project = pm.GetCurrentProject()
tl      = project.GetCurrentTimeline()
time    = tl.GetCurrentTimecode()
fps     = project.GetSetting("timelineFrameRate")

print (" ")
print ("=========================================================================")
print   ("Project '" + project.GetName() +"':")
print   ("  Framerate " + project.GetSetting("timelineFrameRate"))
print ("=========================================================================")
print (" ")

clips       = tl.GetItemListInTrack("Audio", 1)   
FirstClip   = clips[0]
Duration    = FirstClip.GetDuration()
FirstClip.DeleteMarkersByColor("Red")
Markers     = FirstClip.GetMarkers() 

print ("Duration of Audio clip: " + str(Duration) + " frames")   


NrOfMarkers = len(Markers)

if (NrOfMarkers > 1):
    print ("Found " + str(NrOfMarkers) + " markers in audio clip")
else: 
    ("Not enough markers: " + str(NrOfMarkers))
    sys.exit()
       

MarkerList = list()

for Marker in Markers:
    MarkerList.append(int(Marker))

MarkerList.sort()   
print ("MArkers found at frames: " + str(MarkerList))           

MarkerSum = 0
for i in range(1,NrOfMarkers):
    MarkerDiff      = MarkerList[i] - MarkerList[i-1]
    MarkerSum       = MarkerSum +  MarkerDiff
    print (str(MarkerDiff) + " between markers [" + str(MarkerList[i-1]) + "] and [" + str(MarkerList[i]) + "]")
   
MarkerDurAvg    = float(MarkerSum)/float(NrOfMarkers-1)
print ("Avg frames between markers: " + str(round(MarkerDurAvg,3)))   
print ("=========================================================================")
 

DurationOfOneBar_Frames = MarkerDurAvg
DurationOfOneBar_Sec    = DurationOfOneBar_Frames/float(fps)
DurationOfOneBeat_Sec   = DurationOfOneBar_Sec/4
bpm                     = 60.0/DurationOfOneBeat_Sec
NrOfBars                = int((Duration-MarkerList[0])/DurationOfOneBar_Frames)

print ("Duration of one 4/4-bar: " + str(DurationOfOneBar_Sec) + " seconds")
print ("Duration of one 4/4-bar: " + str(DurationOfOneBar_Frames) + " FRAMES")
print ("Estimated BPM (4/4): " + str(round(bpm,1 )))
print ("Number of bars: " + str(NrOfBars))
print ("=========================================================================")

for i in range(1,NrOfBars):
    NextMarker  = int(float(i)*float(DurationOfOneBar_Frames)+ float(MarkerList[0]))
    LastMarker  = int(float(i-1)*float(DurationOfOneBar_Frames)+ float(MarkerList[0]))
    Dur         = NextMarker - LastMarker
    isSuccess   = FirstClip.AddMarker(NextMarker, "Red", "Beat" + str(i), "", 1)
               
    #if isSuccess:
     # print("Added marker after " + str(Dur) + " frames")
   
print ("=========================================================================")
print  ("DONE")
print ("=========================================================================")

Return to DaVinci Resolve

Who is online

Users browsing this forum: apessino, Baidu [Spider], Google [Bot], Google Feedfetcher, Jose Martinez, nukunukoo, panos_mts, raarts, vberenguel and 82 guests