SetVideoEncoderConfigurations
vinnitu opened this issue · 4 comments
How to change encoder Quality (or any) options?
It is also very necessary
I wrote a function to set the configuration according to the documentation, but my camera swears at startup that the configuration is missing, can someone tell me what I did wrong?
I added my setVideoEncoderConfiguration function to /lib/service-media.js
According to documentation: https://www.onvif.org/ver10/media/wsdl/media.wsdl
my function:
OnvifServiceMedia.prototype.setVideoEncoderConfiguration = function(params, callback) {
let promise = new Promise((resolve, reject) => {
let err_msg = '';
if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) {
reject(new Error('The value of "params" was invalid: ' + err_msg));
return;
}
if(err_msg = mOnvifSoap.isInvalidValue(params['Configuration'], 'object')) {
reject(new Error('The "Configuration" property was invalid: ' + err_msg));
return;
}
if(err_msg = mOnvifSoap.isInvalidValue(params['ForcePersistence'], 'boolean')) {
reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg));
return;
}
let soap_body = '';
soap_body += '<trt:setVideoEncoderConfiguration>';
soap_body += '<Configuration>';
soap_body += '<tt:token>' + params['Configuration']['$']['token'] + '</tt:token>';
soap_body += '<tt:Name>' + params['Configuration']['Name'] + '</tt:Name>';
soap_body += '<tt:UseCount>' + params['Configuration']['UseCount'] + '</tt:UseCount>';
soap_body += '<tt:GuaranteedFrameRate>' + params['Configuration']['GuaranteedFrameRate'] + '</tt:GuaranteedFrameRate>';
soap_body += '<tt:Encoding>' + params['Configuration']['Encoding'] + '</tt:Encoding>';
soap_body += '<tt:Resolution>';
soap_body += '<Width>' + params['Configuration']['Resolution']['Width'] + '</Width>';
soap_body += '<Height>' + params['Configuration']['Resolution']['Height'] + '</Height>';
soap_body += '</tt:Resolution>';
soap_body += '<tt:Quality>' + params['Configuration']['Quality'] + '</tt:Quality>';
soap_body += '<tt:Multicast>';
soap_body += '<Address>';
soap_body += '<Type>' + params['Configuration']['Multicast']['Address']['Type'] + '</Type>';
soap_body += '<IPv4Address>' + params['Configuration']['Multicast']['Address']['IPv4Address'] + '</IPv4Address>';
soap_body += '</Address>';
soap_body += '<Port>' + params['Configuration']['Multicast']['Port'] + '</Port>';
soap_body += '<TTL>' + params['Configuration']['Multicast']['TTL'] + '</TTL>';
soap_body += '<AutoStart>' + params['Configuration']['Multicast']['AutoStart'] + '</AutoStart>';
soap_body += '</tt:Multicast>';
soap_body += '<tt:SessionTimeout>' + params['Configuration']['SessionTimeout'] + '</tt:SessionTimeout>';
/*
https://www.onvif.org/ver10/media/wsdl/media.wsdl - page 75 SetVideoEncoderConfiguration
RateControl - optional; [VideoRateControl]
MPEG4 - optional; [Mpeg4Configuration]
H264 - optional; [H264Configuration]
*/
soap_body += '</Configuration>';
soap_body += '<ForcePersistence>' + params['ForcePersistence'] + '</ForcePersistence>';
soap_body += '</trt:setVideoEncoderConfiguration>';
let soap = this._createRequestSoap(soap_body);
//console.log(soap);
//return;
mOnvifSoap.requestCommand(this.oxaddr, 'setVideoEncoderConfiguration', soap).then((result) => {
resolve(result);
}).catch((error) => {
reject(error);
});
});
if(callback) {
promise.then((result) => {
callback(null, result);
}).catch((error) => {
callback(error);
});
} else {
return promise;
}
};
and wrote my own script to set the configuration on the camera:
const onvif = require('node-onvif');
let device = new onvif.OnvifDevice({
'xaddr': 'http://192.168.1.151:8899/onvif/device_service',
'user': 'admin',
'pass': 'xxxxxxxxx'
});
device.init().then((cam) => {
try {
// Get a list of ENCODER encoding configurations
device.services.media.getVideoEncoderConfigurations().then((result) => {
result.data.GetVideoEncoderConfigurationsResponse.Configurations.forEach((data) => {
//console.log(data);
if (data.Encoding == 'JPEG') {
//console.log(data['$'].token + ' ' + data.Encoding);
// get encoder options
var params = {'ConfigurationToken': data['$'].token};
device.services.media.getVideoEncoderConfigurationOptions(params).then((result) => {
//console.log(JSON.stringify(result.data.GetVideoEncoderConfigurationOptionsResponse.Options.JPEG.ResolutionsAvailable, null, ' '));
// update the encoder configuration
data.UseCount = 100;
data.GuaranteedFrameRate = false;
data.Resolution = {Width: '1920', Height: '1080'};
data.Quality = 3;
// RateControl didn't make optional
data.RateControl = {
FrameRateLimit: '-3600',
EncodingInterval: '0',
BitrateLimit: '512'
};
var params = {'Configuration': data, 'ForcePersistence': true};
device.services.media.setVideoEncoderConfiguration(params).then((result) => {
console.log(JSON.stringify(result.data, null, ' '));
}).catch((error) => {
console.error('Error setVideoEncoderConfiguration');
console.error(error);
});
}).catch((error) => {
console.error('Error getVideoEncoderConfigurationOptions');
console.error(error);
});
}
});
}).catch((error) => {
console.error('error getVideoEncoderConfigurations');
console.error(error);
});
} catch (e) {
console.log('Error ' + e.name + ":" + e.message + "\n" + e.stack); // (3) <--
}
}).catch((error) => {
console.error('device.init error');
console.error(error);
});
The result of the execution upset me ... :(
smarthome@smarthome:~/mytest$ node onvif_test.js
Error setVideoEncoderConfiguration
Error: 400 Bad Request - Config Not Exist
at /home/smarthome/mytest/node_modules/node-onvif/lib/modules/soap.js:143:16
at processTicksAndRejections (internal/process/task_queues.js:97:5)
smarthome@smarthome:~/mytest$
Sended soap xml:
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope
xmlns:s="http://www.w3.org/2003/05/soap-envelope"
xmlns:trt="http://www.onvif.org/ver10/media/wsdl"
xmlns:tt="http://www.onvif.org/ver10/schema">
<s:Header>
<Security s:mustUnderstand="1"
xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<UsernameToken>
<Username>admin</Username>
<Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">aaaaaaaaaaaaaaaaaaaaaaa</Password>
<Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">bbbbbbbbbbbbbbbbbbbbbb</Nonce>
<Created
xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2022-11-20T13:40:38.471Z
</Created>
</UsernameToken>
</Security>
</s:Header>
<s:Body>
<trt:setVideoEncoderConfiguration>
<Configuration>
<tt:token>V_ENC_002</tt:token>
<tt:Name>V_ENC_002</tt:Name>
<tt:UseCount>100</tt:UseCount>
<tt:GuaranteedFrameRate>false</tt:GuaranteedFrameRate>
<tt:Encoding>JPEG</tt:Encoding>
<tt:Resolution>
<Width>1920</Width>
<Height>1080</Height>
</tt:Resolution>
<tt:Quality>3</tt:Quality>
<tt:Multicast>
<Address>
<Type>IPv4</Type>
<IPv4Address>239.0.1.0</IPv4Address>
</Address>
<Port>32002</Port>
<TTL>2</TTL>
<AutoStart>false</AutoStart>
</tt:Multicast>
<tt:SessionTimeout>PT10S</tt:SessionTimeout>
</Configuration>
<ForcePersistence>true</ForcePersistence>
</trt:setVideoEncoderConfiguration>
</s:Body>
</s:Envelope>
Something is starting to clear up, I added a token to the Configuration and the error has changed!
soap_body += '<Configuration token="' + params['Configuration']['$']['token'] + '">';
result:
Error: 400 Bad Request - The configuration parameters are not possible to set
Either I am not setting the configuration parameters correctly, or my camera does not support setting these parameters.
If I unset my values, and try to just set the same configuration options as I thought I would get
/*
// update the encoder configuration
data.GuaranteedFrameRate = false;
data.Resolution = {Width: '1920', Height: '1080'};
data.Quality = 3;
// RateControl didn't make optional
data.RateControl = {
FrameRateLimit: '-3600',
EncodingInterval: '0',
BitrateLimit: '512'
};
*/
I get an interesting error...
Error: The device seems to not support the setVideoEncoderConfiguration() method.
Perhaps because I send the same configuration that I thought. And the camera, realizing that nothing has changed, gives me such an error.
The final version of my function looks like this.
OnvifServiceMedia.prototype.setVideoEncoderConfiguration = function(params, callback) {
let promise = new Promise((resolve, reject) => {
let err_msg = '';
if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) {
reject(new Error('The value of "params" was invalid: ' + err_msg));
return;
}
if(err_msg = mOnvifSoap.isInvalidValue(params['Configuration'], 'object')) {
reject(new Error('The "Configuration" property was invalid: ' + err_msg));
return;
}
if(err_msg = mOnvifSoap.isInvalidValue(params['ForcePersistence'], 'boolean')) {
reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg));
return;
}
let soap_body = '';
soap_body += '<trt:setVideoEncoderConfiguration>';
soap_body += '<Configuration token="' + params['Configuration']['$']['token'] + '">';
soap_body += '<tt:token>' + params['Configuration']['$']['token'] + '</tt:token>';
soap_body += '<tt:Name>' + params['Configuration']['Name'] + '</tt:Name>';
soap_body += '<tt:UseCount>' + params['Configuration']['UseCount'] + '</tt:UseCount>';
soap_body += '<tt:GuaranteedFrameRate>' + params['Configuration']['GuaranteedFrameRate'] + '</tt:GuaranteedFrameRate>';
soap_body += '<tt:Encoding>' + params['Configuration']['Encoding'] + '</tt:Encoding>';
soap_body += '<tt:Resolution>';
soap_body += '<Width>' + params['Configuration']['Resolution']['Width'] + '</Width>';
soap_body += '<Height>' + params['Configuration']['Resolution']['Height'] + '</Height>';
soap_body += '</tt:Resolution>';
soap_body += '<tt:Quality>' + params['Configuration']['Quality'] + '</tt:Quality>';
soap_body += '<tt:Multicast>';
soap_body += '<Address>';
soap_body += '<Type>' + params['Configuration']['Multicast']['Address']['Type'] + '</Type>';
soap_body += '<IPv4Address>' + params['Configuration']['Multicast']['Address']['IPv4Address'] + '</IPv4Address>';
soap_body += '</Address>';
soap_body += '<Port>' + params['Configuration']['Multicast']['Port'] + '</Port>';
soap_body += '<TTL>' + params['Configuration']['Multicast']['TTL'] + '</TTL>';
soap_body += '<AutoStart>' + params['Configuration']['Multicast']['AutoStart'] + '</AutoStart>';
soap_body += '</tt:Multicast>';
soap_body += '<tt:SessionTimeout>' + params['Configuration']['SessionTimeout'] + '</tt:SessionTimeout>';
/*
https://www.onvif.org/ver10/media/wsdl/media.wsdl - page 75 SetVideoEncoderConfiguration
RateControl - optional; [VideoRateControl]
MPEG4 - optional; [Mpeg4Configuration]
H264 - optional; [H264Configuration]
*/
soap_body += '</Configuration>';
soap_body += '<ForcePersistence>' + params['ForcePersistence'] + '</ForcePersistence>';
soap_body += '</trt:setVideoEncoderConfiguration>';
let soap = this._createRequestSoap(soap_body);
mOnvifSoap.requestCommand(this.oxaddr, 'setVideoEncoderConfiguration', soap).then((result) => {
resolve(result);
}).catch((error) => {
reject(error);
});
});
if(callback) {
promise.then((result) => {
callback(null, result);
}).catch((error) => {
callback(error);
});
} else {
return promise;
}
};
I hope my work is useful to you.
right now not have camera, can't test ((
but tell me please in your case does it work?