Playground biometrics demo BioID home page

gRPC Method VideoLivenessDetection

Performs liveness detection on a video.

When we receive a video for liveness detection, we perform a passive liveness detection on a bunch of equidistant sampled frames of the video. A decision is made, when one of the breaking conditions is reached:

  • A minimum number of live decisions (currently 7) has been made ⇒ the video is considered live.
  • A minimum number of fake decisions (currently 7) has been made ⇒ the video is considered to be a fake.
  • A maximum number of failures has been reached (currently 5) or not enough frames are available ⇒ the process is aborted with an FailureToAcquire error.

Service method definition

The VideoLivenessDetection API is defined as a unary RPC:

rpc VideoLivenessDetection (VideoLivenessDetectionRequest) returns (LivenessDetectionResponse);

message VideoLivenessDetectionRequest {
    bytes video = 1;
}
message LivenessDetectionResponse {
    JobStatus status = 1;
    repeated JobError errors = 2;
    repeated ImageProperties image_properties = 3;
    bool live = 4;
    double liveness_score = 5;
}

Request

The VideoLivenessDetectionRequest message has a single field:

video
The binary input video data.

Request Headers

This API requires a valid JWT in the Authorization request header and accepts an optional reference number.

Authorization Required Bearer authentication. Please refer to BWS API Authentication for a description of how to provide a valid JWT here.
Reference-Number Optional, client specific reference number, which will be added to the BWS bookkeeping as well as to the response header. You typically use this reference to link the resulting BWS bookkeeping entries with your logs.

Response

On success the API returns a LivenessDetectionResponse message with the fields as follows:

status
The status of the BWS job that processed the request. The following fields are typically only set, when the job has succeeded.
errors
A list of errors that might have occurred while the request has been processed.
image_properties
The calculated image properties for each of the processed frames.
live
The liveness decision made by BWS. If this field is set to true, the provided video is supposed to be recorded from a live person. No errors are reported in this case. When this field is set to false, there is at least one error reported that explains, why the provided video is supposed not to be recorded from a live person.
liveness_score

An informative liveness score (a value between 0.0 and 1.0) that reflects the confidence level of the live decision. The higher the score, the more likely the person is a live person. If this score is exactly 0.0, it has not been calculated and an error has been be reported.

The liveness score is the average of all calculated liveness detection scores. For the liveness decision, the individual liveness detection scores of the processed frames are used.

BWS Errors

In case that the live field is set to false, at least one of the following errors is reported in the errors field:

FailureToAcquire
The video does not contain enough images with exactly one suitable face in it.
RejectedByPassiveLiveDetection
A minimum number of frames in this video indicate, that video is not recorded from a live person.

gRPC Errors

Beside of the success return status code OK (0), this call might also return one of the following gRPC error status codes to indicate an error:

Cancelled (1)
Client application cancelled the request.
Unknown (2)
Server experienced some unexpected behaviour.
InvalidArgument (3)
Client specified an invalid argument: The service cannot decode the provided input data, e.g. because the format cannot be detected.
DeadlineExceeded (4)
Deadline expired before operation could complete.
Internal (13)
Internal errors indicate that critical system invariants have been violated. If you encounter one of these errors, it means something is severely wrong. These errors can occur due to an invalid service configuration, an authenticated client no longer being found, or any other unexpected exception.
Unavailable (14)
The service is currently unavailable. This is most likely a transient condition and may be corrected by retrying with a backoff.
Unauthenticated (16)
The request does not have valid authentication credentials for the operation.

Response Headers/Trailers

All successful BWS gRPC calls return a response header and a response trailer containing additional information about the request:

Response Header
jobid The Job-ID (a GUID) that has been assigned to this BWS call.
bws-version The version of the BWS gRPC service.
reference-number An optional reference number as provided in the request header.
date The timestamp when the request has been received at the server.
... Other headers that might have been added by the server (NGINX, Kestrel, ...) that was handling the request.
Response Trailer
response-time-ms The timespan in milliseconds the request spent at the BWS service.
... Other trailers, like exception trailers, which are added by the gRPC framework in case an RPC exception occurred.

Example:

Here is a short example of how to call into the VideoLivenessDetection gRPC API using a video loaded from a file.

Please refer to BWS API Authentication for a description of the methods CreateAuthenticatedChannel and GenerateToken.

The tooling package Grpc.Tools can be used to generate the C# assets from the bws.proto file. Refer to overview for gRPC on .NET to learn more about how to call into a gRPC service with a .NET client.

try
{
    using GrpcChannel channel = CreateAuthenticatedChannel(new Uri(options.Host), GenerateToken(options.ClientId, options.Key));
    var client = new BioIDWebService.BioIDWebServiceClient(channel);
    var request = new VideoLivenessDetectionRequest { Video = ByteString.CopyFrom(File.ReadAllBytes(options.File)) };
    var call = client.VideoLivenessDetectionAsync(request);
    LivenessDetectionResponse response = await call.ResponseAsync.ConfigureAwait(false);
    // ...
    Console.WriteLine($"This was live: {response.Live} (confidence: {response.LivenessScore:F2})");
}
catch (RpcException ex)
{
    Console.Error.WriteLine($"gRPC error from calling service: {ex.Status.StatusCode} - '{ex.Status.Detail}'");
}

To generate Java classes from a bws.proto file use the Protobuf compiler (protoc) with the command in cmd or in terminal : protoc --java_out=OUTPUT_DIR bws.proto For gRPC client stubs, add the gRPC plugin and use the command: protoc --java_out=OUTPUT_DIR --grpc-java_out=OUTPUT_DIR --plugin=protoc-gen-grpc-java=PATH_TO_PLUGIN bws.proto For a detailed step by step guide on protobuf usage with Java, please refer to Java detailed guide

import java.util.concurrent.CompletableFuture;
import com.bioid.services.BioIDWebServiceGrpc;
import com.bioid.services.BioIDWebServiceGrpc.BioIDWebServiceStub;
import com.bioid.services.Bws.LivenessDetectionResponse;
import com.bioid.services.Bws.VideoLivenessDetectionRequest;
import com.google.protobuf.ByteString;
import io.grpc.ManagedChannel;
import io.grpc.StatusRuntimeException;
import io.grpc.stub.StreamObserver;

public void videoLivenessDetectionAsync( byte[] video)
{
    try
    {
        String jwtToken = generateToken(options.clientId, option.secretKey, options.expireMinutes);
        ManagedChannel channel = createAuthenticatedChannel(option.host, jwtToken);

        BioIDWebServiceStub bwsClientAsync = BioIDWebServiceGrpc.newStub(channel);
        VideoLivenessDetectionRequest videoRequest = VideoLivenessDetectionRequest.newBuilder()
                .setVideo(ByteString.copyFrom(video))
                .build();

        CompletableFuture <LivenessDetectionResponse> videoLivenessResult=new CompletableFuture <>();
        bwsClientAsync.videoLivenessDetection(videoRequest, new StreamObserver <LivenessDetectionResponse>() {
            @Override
            public void onNext(LivenessDetectionResponse value)
            {
                videoLivenessResult.complete(value);
            }
            @Override
            public void onError(Throwable t)
            {
                videoLivenessResult.completeExceptionally(t);
            }
            @Override
            public void onCompleted()
            {
            }
        });
        LivenessDetectionResponse videoLivenessDetecionResponse = videoLivenessResult.get();
        System.out.printf("This was live: %s - Confidence: %f", videoLivenessDetecionResponse.getLive(), videoLivenessDetecionResponse.getLivenessScore());
    } catch (StatusRuntimeException ex)
    {
        System.err.printf("gRPC error from calling service: %s - '%s'", ex.getStatus(), ex.getStatus().getDescription());
    } catch (Exception ex)
    {
        System.err.printf("Error processing images: " + ex.getMessage());
    }
}

Using the protocol buffer compiler protoc (install: python -m pip install grpcio-tools) from the Phython gRPC tools you can create the Phyton client code from the .proto service definition:
python -m grpc_tools.protoc --proto_path=. --python_out=. --grpc_python_out=. bws.proto

import grpc
import bws_pb2_grpc
import bws_pb2

token = GenerateToken(args.clientid, args.key, 10)
with CreateAuthenticatedChannel(args.host, token) as channel:
    stub = bws_pb2_grpc.BioIDWebServiceStub(channel)
    request = bws_pb2.VideoLivenessDetectionRequest()
    with open(args.file, 'rb') as f:
        request.video = f.read()
    try:
        response = stub.VideoLivenessDetection(request)
    except grpc.RpcError as rpc_error:
        print("Received error: ", rpc_error)

    print response