terça-feira, 26 de novembro de 2013

node-django-admin version 0.0.9

I'm using the bootstrap resources to enhance the demo app front-end.

List view

Edit view with a ref (lookup) field and a select field

segunda-feira, 25 de novembro de 2013

node-django-admin version 0.0.8

Since this version we are using Twitter Bootstrap in the demo app.


The ref (lookup) and select widgets are basic, but operational, as we can see in the following image.


quinta-feira, 7 de novembro de 2013

node-django-admin

A Node.js admin site tool inspired by the Django framework admin site tool.

It requires express and mongoose.

list view

edit view with a select field

See the page project at GitHub for more info.

https://github.com/nodeminderjs/node-django-admin

quinta-feira, 21 de março de 2013

The system must be more modular!

I'm testing a new extremely cheap image capture device called EasyCAP 002 USB 2.0 DVR and I noted that the system should be more modular to accept distinct capture devices such as a Geovision GV-800 card and an USB capture device EasyCAP, as shown in the picture below.

So, I decided to rewrite all the grab module to turn this more modular and accept different capture devices hardware. I hope it will be available in the next release 0.1.0.

Links:

sexta-feira, 8 de março de 2013

Release 0.0.9

Release notes

  • Refactored the event recording routine to use /dev/shm buffers to store the frames used to create the video.
  • Refactored grabc to use mmap instead read capture method.
  • Added continuous recording mode.
  • Configured a delay to start each device grab process.
  • Added '-preset veryfast' parameter to create video ffmpeg command.
  • New /scripts folder to store some usefull scripts.
  • New /app/scripts folder to store some shell scripts used by the system.
  • New client features: snap, keyboard keys to move and resize cameras, context menu, main menu and more.
  • Moved the saved client grid configurations from the client to the server.
  • Cameras thumbnails.
  • New main page with thumbnails and more links.
  • New configuration parameters.
  • New cameras parameters: rec_fps and remote_fps.
  • Adjust the cameras fps rate relative to the real device fps rate.

Screenshots


Main page

Customized grid page

Events page

quarta-feira, 13 de fevereiro de 2013

Release 0.0.8

Release notes

  • Unified view and grid views. A grid is a view with multiple cameras and a view has only one camera view. Same views, javascript files and stylesheets for both.
  • New getCamerasSortedArray() method in config to return a sorted cameras array. This is used to display the cameras list properly ordered.

sexta-feira, 8 de fevereiro de 2013

Release 0.0.7

Release notes

  • Implemented the grab exit event to try to rerun the process after a short delay.
  • Max video time limit in seconds.
  • Links to grid, views and events in the cameras list at the main page.

quinta-feira, 7 de fevereiro de 2013

Release 0.0.6


Release notes


  • Socket.io reconnect ok. Moved the for loop that emits subscribe events for the cameras into the connect event. After reconnect this event is fired again.
  • Alert box to show client disconnect.
  • Fixed a bug in using the '(new Date()).toISOString().substr(0,10)' expression to get the date folder name where the recordings are saved. The time returned did not consider the  timezone.
  • Added -y option in ffmpeg command to overwrite output files without asking.

sexta-feira, 1 de fevereiro de 2013

Release 0.0.5

Release notes

  • New page for viewing the recorded events.
  • Fixed bug with event mp4 video generated. Added "-pix_fmt yuv420p" output parameter to the ffmpeg command. Now the generated video plays in Google Chrome browse.

Convert multiple jpeg files to mp4 video using ffmpeg

This doesn't work:

ffmpeg -r 2 -f image2 -i %05d.jpg out.mp4

The video generated doesn't play in Chrome.

The problem is with the pixel format. This is the correct way to generate the video:

ffmpeg -r 2 -f image2 -i %05d.jpg -pix_fmt yuv420p out2.mp4

terça-feira, 29 de janeiro de 2013

Release 0.0.4

Screenshots from release 0.0.4


Grid view with a customized layout showing some dragged and resized cameras:


A singled camera viewed from an iPhone:


The home/configuration page showing all my five configured cameras:


Release notes


  • Fixed the problem with multichannel cards. Reads from multiple cameras connected to the same chip (device - e.g. /dev/video0) are now synchronous.
  • Implemented a simple image change detection routine to trigger event recording.
  • Improvements in the client (browser) to allow grid camera view positioning and resizing, saving these customizations using HTML5 localStorage feature.
  • Events recording for each configured camera.

sexta-feira, 18 de janeiro de 2013

Let's rock the client

The next image shows how the cameras were displayed in the client browser. So annoying, the image of each camera after the previous, all the same size. Without possibility of any sort of customization. Really very annoying!


So, let's start with a little of rock and roll in this project. Let's use tiny drops of jQuery UI to move and resize the camera images the way we want.

For the times they are a-changin. In the next image we can see how the presentation is now. We can freely move and resize each camera image regardless of the other cameras sizes and positions. We may even overlap then.


The coolest thing is that we can do it all with very few new lines of code.

Some relevant parts of the Jade script:

doctype 5
html
  head
    ...
    link(rel='stylesheet', href='http://code.jquery.com/ui/1.10.0/themes/base/jquery-ui.css')
    script(src='/javascripts/jquery.min.js')
    script(src='/javascripts/jquery-ui.custom.min.js')
    ...
    script
      $(function() {
        $(".draggable").draggable();
        $(".resizable").resizable({
          aspectRatio: 320 / 240
        });        
      });
  body
    #grid
      .linha
        #cam01.camera.draggable
          .image
            img#img01.resizable(src='#', width=320, height=240) 
          .info
        ...

The fifth element

Installing the fifth camera for testing, we had problems and this did not work at all.

Searching in Google, I remembered that the GV-800 card is a multichannel card with four Bt8xx chips, each one with four channels, that is, each chip can control up to four cameras.

The problem is that each chip can control only one camera at a time, and we can not read two or more of these four cameras simultaneously. So we must have some synchronization mechanism to control the capture from these cameras connected to the same chip (device).



So, a implemented a function that acquires a exclusive lock on the device file descriptor (/dev/video0, /dev/video1, etc).

void acquire_file_lock(int fd, int retry_ms)
{
  int rc;

  for (;;) {
    rc = flock(fd, LOCK_EX | LOCK_NB); // grab exclusive lock, fail if can't obtain.
    if (rc == -1) {
      // fail - sleep retry_ms (ms) and try again
      xsleep(0, retry_ms);
    } else {
      // success - return
      return;
    }
  }
}

In the main loop that reads the device, we acquire the lock, read the device and release the lock, ensuring the synchronization between the cameras connected to the same device, preventing concurrent accesses.

static void mainloop(void)
{
  ...

  while (1) {
    acquire_file_lock(fd, 10);
    init_device();

    // read the device - capture frame
    ...

    release_file_lock(fd);

    ...
  } // while (1)
}

This way, our fifth camera started to work ok.

Links:

quarta-feira, 9 de janeiro de 2013

Release 0.0.3

In this third release, the project is becoming more functional and stable.

We already have a configuration file with server and cameras configuration options. See the wiki configuration page.

Some screenshots from this release:



See more details in our github page.

terça-feira, 8 de janeiro de 2013

How to make a zebra-striped table with Jade

This is a very simple tutorial on how to make a zebra-striped table, such as the one below, using the Jade template engine.


The jade template looks like this:

  table#cameras
    thead
      tr.head
        th Camera
        th Description
        th Type
        th Device
        th Channel
        th Format
        th Palette
        th Width
        th Height
        th Fps
    tbody
      - var i = -1
      each val, key in cameras
        - ++i
        tr(class=(i % 2 == 0) ? 'odd' : 'even')
          td #{key}
          td #{val.descr}
          td #{val.type}
          td #{val.device}
          td #{val.channel}
          td #{val.format}
          td #{val.palette}
          td #{val.width}
          td #{val.height}
          td #{val.fps}

Note the lines prefixed with a hyphen (-), the first one creates a var and the second increments this var inside the each loop.

In the loop it cycles between 'odd' and 'even' tr class, depending on the i var value.

The stylus template looks like this:

table#cameras tr.odd
  background-color: #444

table#cameras tr.even
  background-color: #888


sexta-feira, 4 de janeiro de 2013

Release 0.0.2

This screenshot shows version 0.0.2 working with two cameras (the second one is defective) connected to a Geovision GV-800 card.


This second release is again a concept proof to test some design and tools options.

No configuration yet, and almost everything is hard coded.

I'm developing this on an Ubuntu 12.04 64 bits server with a GV-800 card with two attached cheap mini-cameras, the second one with malfunction, as we can see above.

See more instructions and comments in our github page.