As of today, Jully 2019, liblinphone python binding is no longer updated. We might rework on this project in the future.

Installation

Download either a stable version or a snapshot of the liblinphone python wrapper.

Linux

Install some dependencies first:

sudo apt-get install python-setuptools
sudo easy_install pip
sudo pip install wheel
sudo pip install --upgrade pip

Then install the linphone python wrapper using pip (replace the file name by the one you downloaded):

sudo pip install linphone-3.10.2_834_gb95a9b8-cp27-none-linux_x86_64.whl

To check if the installation was successful, launch a python shell, and in the python prompt (>>>), enter:

import linphone

If you get no error message and an other prompt >>> then everything is ok! Otherwise you are welcome to explain the error you are having of the linphone-users mailing-list.

Getting started

Here is a simple python program that performs the functionality of a security camera.

If you are using the Raspberry PI camera module instead of an external webcam, make sure you load the appropriate kernel module in order to get video: sudo modprobe bcm2835-v4l2

#!/usr/bin/env python

import linphone
import logging
import signal
import time

class SecurityCamera:
def __init__(self, username='', password='', whitelist=[], camera='', snd_capture='', snd_playback=''):
 self.quit = False
 self.whitelist = whitelist
  callbacks = linphone.Factory.get().create_core_cbs()
  callbacks.call_state_changed = self.call_state_changed

 # Configure the linphone core
  logging.basicConfig(level=logging.INFO)
  signal.signal(signal.SIGINT, self.signal_handler)
  linphone.set_log_handler(self.log_handler)
 self.core = linphone.Factory.get().create_core(callbacks, None, None)
 self.core.max_calls = 1
 self.core.echo_cancellation_enabled = False
 self.core.video_capture_enabled = True
 self.core.video_display_enabled = False
 self.core.nat_policy.stun_server = 'stun.linphone.org'
 self.core.nat_policy.ice_enabled = True
 if len(camera):
  self.core.video_device = camera
 if len(snd_capture):
  self.core.capture_device = snd_capture
 if len(snd_playback):
  self.core.playback_device = snd_playback

 # Only enable PCMU and PCMA audio codecs
 for codec in self.core.audio_codecs:
  if codec.mime_type == "PCMA" or codec.mime_type == "PCMU":
   self.core.enable_payload_type(codec, True)
  else:
   self.core.enable_payload_type(codec, False)

 # Only enable VP8 video codec
 for codec in self.core.video_codecs:
  if codec.mime_type == "VP8":
   self.core.enable_payload_type(codec, True)
  else:
   self.core.enable_payload_type(codec, False)

 self.configure_sip_account(username, password)

def signal_handler(self, signal, frame):
 self.core.terminate_all_calls()
 self.quit = True

def log_handler(self, level, msg):
  method = getattr(logging, level)
  method(msg)

def call_state_changed(self, core, call, state, message):
 if state == linphone.CallState.IncomingReceived:
  if call.remote_address.as_string_uri_only() in self.whitelist:
    params = core.create_call_params(call)
    core.accept_call_with_params(call, params)
  else:
    core.decline_call(call, linphone.Reason.Declined)
    chat_room = core.get_chat_room_from_uri(self.whitelist[0])
    msg = chat_room.create_message(call.remote_address_as_string + ' tried to call')
    chat_room.send_chat_message(msg)

def configure_sip_account(self, username, password):
 # Configure the SIP account
  proxy_cfg = self.core.create_proxy_config()
  proxy_cfg.identity_address = self.core.create_address('sip:{username}@sip.linphone.org'.format(username=username))
  proxy_cfg.server_addr = 'sip:sip.linphone.org;transport=tls'
  proxy_cfg.register_enabled = True
 self.core.add_proxy_config(proxy_cfg)
  auth_info = self.core.create_auth_info(username, None, password, None, None, 'sip.linphone.org')
 self.core.add_auth_info(auth_info)

def run(self):
 while not self.quit:
  self.core.iterate()
   time.sleep(0.03)

def main():
 cam = SecurityCamera(username='raspberry', password='pi', whitelist=['sip:trusteduser@sip.linphone.org'], camera='V4L2: /dev/video0', snd_capture='ALSA: USB Device 0x46d:0x825')
 cam.run()

main()

The sample above has been tested on version 3.10.2_834. If you are using an older version (or a newer), the API might be different and the code will generate an error when running.

Basically, it:

  • registers on sip.linphone.org with the account 'raspberry' and the password 'pi' (hint: change these values for you own ones in the main() function)
  • listens for incoming calls
  • automatically answers to an incoming call if it comes from one of the SIP addresses in the whitelist (in this case from 'sip:trusteduser@sip.linphone.org')
  • declines the incoming calls coming from other SIP addresses
  • sends a chat message to the first SIP address in the whitelist (considered as the administrator) if someone that is not authorized to do so calls the security camera

Other interesting things to note are that:

  • the echo canceller is disabled because it uses a lot of CPU power which the Raspberry PI does not have. And it is not really useful for that use case.
  • the only audio codecs enabled are PCMU and PCMA for the same reason. Other codecs such as speex or opus require too much CPU if we want to also have the video.
  • the VP8 codec is used for video.
  • the camera device, the sound capture device and the sound playback device are configurable. Just change the corresponding values in the main() function. The available values are listed in the logs when starting the program.

This is just a basic code example that can be greatly improved and to which a lot of features can be added. For example, you could perform some actions when receiving a chat message.

The API documentation can be found at http://pythonhosted.org/linphone/.

You are more than welcome to exchange all the useful feature you achieve on the linphone-users mailing-list!

Tags: python wrapper