obsproject / obs-websocket

Remote-control of OBS Studio through WebSocket
GNU General Public License v2.0
3.84k stars 704 forks source link

Feature Request: Add percentage of volume on InputVolumeChanged event #1084

Open grofit opened 1 year ago

grofit commented 1 year ago

Feature Request Type

RPC Event

Feature Request Type (Other)

No response

Requested Feature

Currently the InputVolumeChanged event outputs an inputVolumeMul value but its not really clear what this value is meant to indicate/represent as currently if I were to put my slider at 50% the event raised would give me a value around 0.16, and at about 3/4 through it gives me a value of about 0.91.

After asking in the discord server it was indicated that it may be using some underlying logarithmic formula, but I have no idea how to calculate the volume as a percentage from the existing inputVolumeMul value and there are no docs around this.

So my request would be to add a new property which is the percentage of the slider, or at least some way to derive the input volume percentage from the event data provided.

Requested Feature Usage Scenario

I need to display a slider in a 3rd party application which represents the OBS volume percentage and let users alter it which would send a message to OBS to set its volume to the given amount.

grofit commented 1 year ago

After discussing in the discord there is some more information which is needed to be understood around how the volume metrics are provided. So the levels are constrained within given thresholds but by default the mul is between 0-1 however you can add more gain in advanced options bumping it up to 0-20 which makes it hard to know if your 1.0 is 100% or 5%, so after discussing with @tt2468 he kindly provided this code which should work for default scenarios to get the percentage from the decibels metric provided.

import math

LOG_RANGE_DB = 96.0
LOG_OFFSET_DB = 6.0

LOG_OFFSET_VAL = -0.77815125038364363
LOG_RANGE_VAL = -2.00860017176191756

def log_def_to_db(deflection: float):
    if deflection >= 100.0:
        return 0.0
    if deflection <= 0.0:
        return -100.0
    deflection = deflection / 100
    return -(LOG_RANGE_DB + LOG_OFFSET_DB) * pow((LOG_RANGE_DB + LOG_OFFSET_DB) / LOG_OFFSET_DB, -deflection) + LOG_OFFSET_DB

def log_db_to_def(db: float):
    if db >= 0.0:
        return 100.0
    if db <= -96.0:
        return 0.0
    return ((-math.log10(-db + LOG_OFFSET_DB) - LOG_RANGE_VAL) / (LOG_OFFSET_VAL - LOG_RANGE_VAL)) * 100.0

While this work around is very useful for others like me who need to work in terms of a 0-100% style interaction for volume, it still feels like the FR is a valid request however if OBS doesnt expose the slider value directly and it HAS to be derived from the metrics it does provide it may end up being a headache for the team to maintain as its custom logic that "could change at any point" if OBS changes how it handles the audio metrics.

Anyway I will leave this FR open as I feel it would be beneficial but at least there is a way to convert the metric using the code above, which should be easy enough to translate into other languages.

tt2468 commented 1 year ago

Unsure what do do here honestly. A deflection value is arguably much more generally useful than a mul value, but it probably also depends on who you ask. It seems like it would be fair to do a minor refactor of how OBS calculates percentage (move it to a libobs util), then replace inputVolumeMul with inputVolumePercent. The one thing to consider (for me) is that OBS internally has multiple calculations for how to convert decibels to deflection, so it would be worth solidifying that we don't change algorithms in the future.