Difference between revisions of "GStreamer Daemon - Javascript Video Player Example"

From RidgeRun Developer Connection
Jump to: navigation, search
(Client side)
m (Example 2: GSTD Controller)
 
(15 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{GStreamer Daemon/Head | previous=API Examples | next=Troubleshooting}}
+
{{GStreamer Daemon/Head | previous=Python Video Player Example | next=Troubleshooting}}
  
 
==Introduction to GStreamer Daemon Javascript Video Player Example ==
 
==Introduction to GStreamer Daemon Javascript Video Player Example ==
Line 12: Line 12:
 
==Usage==
 
==Usage==
 
=== Server side ===
 
=== Server side ===
 +
A regular localhost setup will use just one computer with the following variables. You can also use a local area network to have multiple devices.
 +
GSTD_ADDRESS=127.0.0.1
 +
GSTD_PORT=5000
 +
SERVER_ADDRESS=127.0.0.1
 +
SERVER_PORT=8000
 +
 
Run gstd
 
Run gstd
  gstd --enable-http-protocol --http-port=192.168.0.114 --htress=5005
+
  gstd --enable-http-protocol --http-address=${GSTD_ADDRESS} --http-port=${GSTD_PORT}
  
 
Then move to web examples and run the server:
 
Then move to web examples and run the server:
 
  cd examples/web/
 
  cd examples/web/
  
ADDRESS = 192.168.0.114
+
  ./setup_http_server.sh -a $SERVER_ADDRESS -p $SERVER_PORT
PORT = 5002
 
  ./setup_http_server.sh -a $ADDRESS -p $PORT'
 
  
 
===Client side===
 
===Client side===
 
On your browser go to:
 
On your browser go to:
  http://192.168.0.114:5002/  (Use the ip and port that you configured in the last step)
+
  http://127.0.0.1:8000/  (Use the IP and port that you configured in the last step)
 
   
 
   
  
 
Now you can see the menu with the available examples
 
Now you can see the menu with the available examples
In this page you need to configure the ip and port where gstd is running, in this case ip=192.168.0.114 and port=5005
+
On this page, you need to configure the IP and Port where GstD is running, in this case, IP=127.0.0.1 and Port=5000.
 
[[File:Menu html.png |900px|center|thumb|Menu gstd examples]]
 
[[File:Menu html.png |900px|center|thumb|Menu gstd examples]]
  
Now select the first example "Video player" and you can see the following page
+
====Example 1: Video player====
 +
Now select the first example "Video player" and you can see the following page. It is possible to enter the example without the menu, in that case, it is necessary to configure the Address and port as shown in the picture.
  
 
[[File:Video_player.png | 900px |center|thumb]]
 
[[File:Video_player.png | 900px |center|thumb]]
Line 37: Line 42:
 
Controls:
 
Controls:
 
* Select the input
 
* Select the input
** Camera: Select the camera that you want to use, eg. '/dev/video0'
+
** Camera: Select the camera that you want to use, '''''e.g. /dev/video0''''' .
 +
** File: Select the video file that you want to use, '''''e.g. /home/user/videos/video.mp4''''' .
 +
* Create the pipelines
 +
* Delete the pipeline
 +
* Play, Pause, Stop
 +
* Speed
 +
* Playback direction ( > Forward, < backward )
 +
* Jump to a specific time
 +
* The console shows the errors, warnings, and logs of gstd
  
==Code Analysis==
+
====Example 2: GSTD Controller====
 +
Now select the second example "GSTD controller" and you can see the following page
 +
It is possible to enter the example without the menu, in that case, it is necessary to configure the Address and port as shown in the picture.
 +
[[File:Gstd controller.png|900px|thumb|center|GSTD controller]]
  
This example application can be divided into 3 sections:
+
Controls:
# Init Sequence & Command Parser
+
* Pipeline e.g '''videotestsrc ! autovideosink'''
# GstcPlayer Class
+
* Create the pipelines
## Error Handler
+
* Delete the pipeline
 
+
* Play, Pause, Stop
===Init Sequence & Command Parser===
+
* Speed
This section is pretty straightforward. You just need to pas the video file path as the only argument.
+
* Playback direction ( > Forward, < backward )
 +
* Jump to a specific time
 +
* The console shows the errors, warnings, and logs of gstd
 +
Advanced controls:
 +
* Elements selection (Select the element to modify the properties)
 +
* Property selection (Select the property that you want to modify)
 +
* New value of the selected property
 +
* Filter the bus
 +
* Send an EOS
 +
* Send a Flush Start and Stop
  
<syntaxhighlight lang=python>
+
==Add your own example==
  if __name__ == "__main__":
+
The two previous applications are just two basic examples to demonstrate its capabilities. It is possible to develop new applications that communicate with Gstd through the [https://developer.ridgerun.com/wiki/index.php?title=GStreamer_Daemon_-_JavaScript_API JavaScript API] or the [https://developer.ridgerun.com/wiki/index.php?title=GStreamer_Daemon_-_HTTP_API HTTP API].
  print("Sample PyGstC Video Player")
 
'''
 
  .
 
  .
 
  .   '''
 
</syntaxhighlight>
 
  
Once the application is started. Automatically, it will open and reproduce the video. On the command prompt, you can specify any of the supported commands.
+
The project repository contains the source code for these examples. They are built with:
 +
# JavaScript to use the Gstd JavaScript API.
 +
# VueJS Components for basic layout and functionalities.
 +
For example, the Video Player Applications is made up of the following components:
 +
.
 +
└── video_player_app
 +
    ├── VideoPlayer
 +
    ├── SelectInput
 +
    ├── ElementsControl
 +
    ├── ChangeProperty
 +
    ├── BusConsole
 +
    ├── BusControl
 +
    ├── FooterControl
 +
    └── GstdControl
 +
The VideoPlayer Component implements most of the communication with Gstd. The developer can integrate this component in any other custom application if the requirements are similar.  
  
===GstcPlayer Class===
+
First, it is necessary to create a new app file copying .e.g "video_player_app.js" and modify this file with the components required, it is necessary to import each component create an instance, and finally add the component to the HTML .e.g "<gstd-control></gstd-control>".
This class contains all the necessary calls to communicate with the GStreamer Daemon, through the Python GstdClient.
 
  
Firs of all the Python GstdClient needs to be imported with:
+
Then it is necessary to modify the '''main.js''' file and add the code to include the new app to the project, copy one of the actual codes that include the apps, and modify it to your own app.
<syntaxhighlight lang=python>
 
from pygstc.gstc import GstcError, GstdError, GstdClient
 
from pygstc.logger import CustomLogger
 
</syntaxhighlight>
 
  
There are two main objects to manipulate the GstdClient over Python. First the Logger class (''CustomLogger'') and the GstdClient itself. The logger can have different information levels, for example you can pass an 'ERROR' level.
+
The next step is copy .e.g "controller_app.html" and modify only this line, with the id that you use in your new app.
<syntaxhighlight lang=python>
+
<pre>
class GstcPlayer:
+
<div id="controller"></div>  
 +
</pre>
  
  def __init__(self, videoPath):
+
Finally, if you want to add the app to the menu go to the '''menu.html''' and add a new row with your new app.
    self.gstd_logger = CustomLogger('simple_playback', loglevel='WARNING')
 
    self.gstc = GstdClient(logger=self.gstd_logger)
 
</syntaxhighlight>
 
  
Once those objects are created. The [[https://developer.ridgerun.com/wiki/index.php?title=GStreamer_Daemon_-_Python_API|Python API]] offers a set of calls to communicate with the GStreamer Daemon. For example, when the ''play'' command is executed, the following actions are executed:
 
<syntaxhighlight lang=python>
 
  def playVideo(self):
 
    self.gstc.pipeline_create(self.pipeName, self.pipeline)
 
    self.gstc.pipeline_play(self.pipeName)
 
</syntaxhighlight>
 
  
Let's say you just want to pause the video and continue from that point. Then you can modify the playing function similar to:
 
<syntaxhighlight lang=python>
 
  def playVideo(self):
 
    if (not self.pipe_exists(self.pipeName)):
 
      self.gstc.pipeline_create(self.pipeName, self.pipeline)
 
    self.gstc.pipeline_play(self.pipeName)
 
  
  def pipe_exists(self, pipe_name):
+
<syntaxhighlight lang=html>
    #Check if pipe is already created
+
<!DOCTYPE html>
    existing_pipes = self.gstc.list_pipelines()
+
<html>
    if (existing_pipes == []):
 
      ret = False
 
    elif( existing_pipes[0]['name'] == pipe_name):
 
      ret = True
 
    else:
 
      ret = False
 
    return ret
 
</syntaxhighlight>
 
  
Then a ''pause'' call can be created with:
+
<head>
<syntaxhighlight lang=python>
+
    <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
  def pauseVideo(self):
+
    <meta content="utf-8" http-equiv="encoding">
     self.gstc.pipeline_pause(self.pipeName)
+
     <title>Gstd HTTP Server Examples</title>
</syntaxhighlight>
 
  
And to use the same ''play'' command:
+
    <link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
 +
    <link type="text/css" rel="stylesheet"
 +
    href="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.css" />
  
Similar, when the command stop is executed there are some instructions to achieve this:
+
    <!-- Load polyfills to support older browsers -->
<syntaxhighlight lang=python>
+
    <script src="https://polyfill.io/v3/polyfill.min.js?features=es2015%2CIntersectionObserver"></script>
  def stopVideo(self)
+
    <link href="https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css" rel="stylesheet">
     self.gstc.pipeline_stop(self.pipeName)
+
    <!-- This is a development version of Vue.js! -->
     self.gstc.pipeline_delete(self.pipeName)
+
     <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</syntaxhighlight>
+
    <script src="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.js"></script>
 +
     <script src="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue-icons.min.js"></script>
 +
    <script src="https://rawcdn.githack.com/RidgeRun/gstd-1.x/feature/http-server-script/libgstc/javascript/libgstc.js"></script>
  
The same process was used to implement changes in playback speed, by using:
+
    <script src="main.js" type="module"></script>
<syntaxhighlight lang=python>
+
</head>
    self.gstc.event_seek(self.pipeName, rate=self.playingSpeed, format=3, flags=1, start_type=1, start=0, end_type=1, end=-1)
 
</syntaxhighlight>
 
You can use the same ''event_seek'' call to select a time to jump on the video.
 
  
====Error Handler====
+
    <div id="video_player"></div>
The Python API offers calls to read messages from the GStreamer Daemon Bus. The very basic command to read from the bus is:
 
<syntaxhighlight lang=python>
 
resp = self.gstc.bus_read(self.pipeName)
 
</syntaxhighlight>
 
  
This call does '''not''' need any use thread to be executed. It can be called at any moment by the user application.
+
<body>
  
For the Video Player, this function is contained within a separate thread just to avoid manually reading from the bus with a command. By doing so we achieved a more complete application, and also for the demonstration purposes. This thread function configures the reading from the bus with a timeout, so we can gracefully exit the thread whenever the user demands so. Also, it is possible to filter the messages by specific types, such as errors or warnings.
+
</body>
  
<syntaxhighlight lang=python>
+
</html>
def errPlayerHandler(self):
 
    self.gstc.bus_timeout(self.pipeName, 1000)
 
    self.gstc.bus_filter(self.pipeName, "error+eos+warning")
 
  
    if(self.pipe_exists(self.pipeName)):
 
        resp = self.gstc.bus_read(self.pipeName)
 
        if (resp != None and resp["type"] == "error"):
 
          print("Info: Video stopped")
 
          self.gstc.pipeline_pause(self.pipeName)
 
          self.gstc.pipeline_stop(self.pipeName)
 
        elif (resp != None and resp["type"] == "eos"):
 
          print("Info: Video stream ended")
 
          self.gstc.pipeline_pause(self.pipeName)
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
With the implemented filters two main actions are detected:
+
{{GStreamer Daemon/Foot | previous=Python Video Player Example | next=Troubleshooting}}
# When the Video finalize reproducing, and then the pipeline is paused.
 
# If an error occurred the pipeline is stopped.
 
 
 
If you inspect the code, you will find that this function has locking objects to avoid race conditions. But for basic understanding, we presented the essentials instructions from the application.
 
 
 
 
 
 
 
{{GStreamer Daemon/Foot | previous=API Examples | next=Troubleshooting}}
 

Latest revision as of 12:45, 23 February 2021


Previous: Python Video Player Example Index Next: Troubleshooting




Introduction to GStreamer Daemon Javascript Video Player Example

This is one concrete usage example of the GStreamer Daemon along with a Javascript + HTML Application. In this case, the application uses the Javascript GSTD API to communicate with GStreamer Daemon through the HTTP server.

The application consists of a Simple Video Player with several capabilities:

  1. Select the input (Camera or video file)
  2. Regular and reverse video playback.
  3. Trick modes (fast-forward, speed change, seek to position).
  4. Read messages from the GSTD bus.

Usage

Server side

A regular localhost setup will use just one computer with the following variables. You can also use a local area network to have multiple devices.

GSTD_ADDRESS=127.0.0.1
GSTD_PORT=5000
SERVER_ADDRESS=127.0.0.1
SERVER_PORT=8000

Run gstd

gstd --enable-http-protocol --http-address=${GSTD_ADDRESS} --http-port=${GSTD_PORT}

Then move to web examples and run the server:

cd examples/web/
./setup_http_server.sh -a $SERVER_ADDRESS -p $SERVER_PORT

Client side

On your browser go to:

http://127.0.0.1:8000/  (Use the IP and port that you configured in the last step)

Now you can see the menu with the available examples On this page, you need to configure the IP and Port where GstD is running, in this case, IP=127.0.0.1 and Port=5000.

Menu gstd examples

Example 1: Video player

Now select the first example "Video player" and you can see the following page. It is possible to enter the example without the menu, in that case, it is necessary to configure the Address and port as shown in the picture.

Video player.png

Controls:

  • Select the input
    • Camera: Select the camera that you want to use, e.g. /dev/video0 .
    • File: Select the video file that you want to use, e.g. /home/user/videos/video.mp4 .
  • Create the pipelines
  • Delete the pipeline
  • Play, Pause, Stop
  • Speed
  • Playback direction ( > Forward, < backward )
  • Jump to a specific time
  • The console shows the errors, warnings, and logs of gstd

Example 2: GSTD Controller

Now select the second example "GSTD controller" and you can see the following page It is possible to enter the example without the menu, in that case, it is necessary to configure the Address and port as shown in the picture.

Error creating thumbnail: Unable to save thumbnail to destination
GSTD controller

Controls:

  • Pipeline e.g videotestsrc ! autovideosink
  • Create the pipelines
  • Delete the pipeline
  • Play, Pause, Stop
  • Speed
  • Playback direction ( > Forward, < backward )
  • Jump to a specific time
  • The console shows the errors, warnings, and logs of gstd

Advanced controls:

  • Elements selection (Select the element to modify the properties)
  • Property selection (Select the property that you want to modify)
  • New value of the selected property
  • Filter the bus
  • Send an EOS
  • Send a Flush Start and Stop

Add your own example

The two previous applications are just two basic examples to demonstrate its capabilities. It is possible to develop new applications that communicate with Gstd through the JavaScript API or the HTTP API.

The project repository contains the source code for these examples. They are built with:

  1. JavaScript to use the Gstd JavaScript API.
  2. VueJS Components for basic layout and functionalities.

For example, the Video Player Applications is made up of the following components:

.
└── video_player_app
    ├── VideoPlayer
    ├── SelectInput
    ├── ElementsControl
    ├── ChangeProperty
    ├── BusConsole
    ├── BusControl
    ├── FooterControl
    └── GstdControl

The VideoPlayer Component implements most of the communication with Gstd. The developer can integrate this component in any other custom application if the requirements are similar.

First, it is necessary to create a new app file copying .e.g "video_player_app.js" and modify this file with the components required, it is necessary to import each component create an instance, and finally add the component to the HTML .e.g "<gstd-control></gstd-control>".

Then it is necessary to modify the main.js file and add the code to include the new app to the project, copy one of the actual codes that include the apps, and modify it to your own app.

The next step is copy .e.g "controller_app.html" and modify only this line, with the id that you use in your new app.

<div id="controller"></div> 

Finally, if you want to add the app to the menu go to the menu.html and add a new row with your new app.


<!DOCTYPE html>
<html>

<head>
    <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
    <meta content="utf-8" http-equiv="encoding">
    <title>Gstd HTTP Server Examples</title>

    <link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
    <link type="text/css" rel="stylesheet"
    href="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.css" />

    <!-- Load polyfills to support older browsers -->
    <script src="https://polyfill.io/v3/polyfill.min.js?features=es2015%2CIntersectionObserver"></script>
    <link href="https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css" rel="stylesheet">
    <!-- This is a development version of Vue.js! -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.js"></script>
    <script src="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue-icons.min.js"></script>
    <script src="https://rawcdn.githack.com/RidgeRun/gstd-1.x/feature/http-server-script/libgstc/javascript/libgstc.js"></script>

    <script src="main.js" type="module"></script>
</head>

    <div id="video_player"></div>

<body>

</body>

</html>


Previous: Python Video Player Example Index Next: Troubleshooting