Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SetVideoEncoderConfigurations #86

Open
vinnitu opened this issue Nov 26, 2021 · 4 comments
Open

SetVideoEncoderConfigurations #86

vinnitu opened this issue Nov 26, 2021 · 4 comments

Comments

@vinnitu
Copy link

vinnitu commented Nov 26, 2021

How to change encoder Quality (or any) options?

@csplkiller
Copy link

It is also very necessary

@csplkiller
Copy link

csplkiller commented Nov 20, 2022

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>


@csplkiller
Copy link

csplkiller commented Nov 20, 2022

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.

@vinnitu
Copy link
Author

vinnitu commented Nov 22, 2022

right now not have camera, can't test ((
but tell me please in your case does it work?

Repository owner deleted a comment from akashakki Mar 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants
@vinnitu @csplkiller and others