bp2008 / ui3

A powerful, modern HTML5 web interface for Blue Iris.
GNU Lesser General Public License v3.0
124 stars 16 forks source link

Ad hoc timelapse #134

Closed pawel-sw closed 1 year ago

pawel-sw commented 1 year ago

``It would be useful to add a new tab in UI3 that can be used to generate ad hoc time-lapses. The same could be achieved by creating a "snap" option on the timeline slider where moving mouse would snap to a specified time, it would have to preload all frames so you can quickly animate when using 4k footage on slow storage.

It is useful if you need to quickly check some event by skimming thru footage at the same time of day over a certain time period, e.g. it could be useful to quickly see how your garden is growing, how are structures deteriorating, or verify certain process that runs on schedule. The difference compared to the timeline is that you can control the time of day so you get the same lighting on every frame. Another advantage of this solution is that it will preload all images, so even you your footage is on a slow storage you can quickly "animate" it.

I've quickly drafted an HTML file that creates ad hoc time-lapses that are controlled with the slider.

How to use:

  1. Edit the HTML file in any text editor and modify the following lines:
    var biUrl = 'http://10.10.10.11:81'          //URL to your BlueIris server
    var cameras = 'Back,Front,FrontDr,Side,Terrace,Doorbell'    //List of cameras for the dropdown
    var username = '<your BI UI3 username>'
    var password = '<your BI UI3 password>'
    var atHour = 12                       //Time of day (hour) at which the image will be captured
    var intervalSeconds = 24 * 60 * 60  //Interval between images, default every 24h
  2. Save and open the file in any browser
  3. Select the camera
  4. Select the time range
  5. Use the slider to "animate"
<!DOCTYPE html>
<html>
<head>
    <script>
        var biUrl = 'http://10.10.10.104:81'
        var cameras = 'Back,Front,FrontDr,Side,Terrace,Doorbell'
        var username = 'ai'
        var password = 'ai'
        var atHour = 12
        var intervalSeconds = 24 * 60 * 60
    </script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
    <script src="//cdn.rawgit.com/placemarker/jQuery-MD5/master/jquery.md5.js"></script>

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"/>
    <link rel="stylesheet" href="https://unpkg.com/bootstrap-datepicker@1.9.0/dist/css/bootstrap-datepicker3.min.css"/>

    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" crossorigin="anonymous"></script>
    <script src="https://unpkg.com/bootstrap-datepicker@1.9.0/dist/js/bootstrap-datepicker.min.js"></script>
    <title>BlueIris Timelapse</title>

</head>
<body>
Camera: <select name="cameras" id="cameras"></select>
<div id="event_period">
    Date start: <input type="text" class="actual_range" id="startDate">
    Date end: <input type="text" class="actual_range" id="endDate">
</div>

<div class="slidecontainer">
    <input type="range" min="0" max="0" value="0" class="slider" id="myRange" style="width: 1000px;">
</div>
<div id="container"></div>

<div style="display: block; height: 2000px; width: 100px;"></div>
<script>
    function addIntervals(date, intervals) {
        var result = new Date(date + intervals*intervalSeconds*1000);
        return result;
    }

    $(document).ready(function () {
        cameras.split(',').forEach(camera => $('#cameras').append(`<option value="${camera}">${camera}</option>`))
        var args = {cmd: "login"};
        $.post("http://10.10.10.105:81/json", JSON.stringify(args),
            function (data, status) {
                args.session = data.session;
                args.response = $.md5(username + ":" + data.session + ":" + password);
                $.post("http://10.10.10.105:81/json", JSON.stringify(args));
            });

        $('#event_period').datepicker({
            inputs: $('.actual_range'),
            todayHighlight: true,
            defaultViewDate: new Date()
        });

        $('#event_period').change(function () {
            var date1 = new Date($('#startDate').val()).setHours(atHour) + 5000
            var date2 = new Date($('#endDate').val()).setHours(atHour) + 5000
            const diffTime = Math.abs(date2 - date1);
            const diffDays = Math.ceil(diffTime / (1000 * intervalSeconds)) + 1;
            let max = diffDays - 1;
            $("#myRange")[0].max = max;
            $("#myRange")[0].value = max;
            $('#container').empty();
            for (let i = 0; i < diffDays; i++) {
                $('#container').append($('<img>', {
                    src:
                        `${biUrl}/time/${$("#cameras").val()}?jpeg=&session=${args.session}&isolate&pos=${addIntervals(date1, i).getTime()}&decode=1&stream=0&w=3840&h=2160`,
                    class: 'animated', style: i === max ? '' : 'display: none;'
                }))
            }
        });

        $("#myRange").on('input propertychange', function () {
            $("#container img").hide();
            $("#container img").eq($('#myRange').val()).show();
        });
    });
</script>

</body>
</html>
bp2008 commented 1 year ago

That is a clever idea using a range slider to select between preloaded images in this manner. Normally timeline seeking is so sluggish. I love highly responsive UI interactions, so this is oddly satisfying to have instant seeking response across a span of weeks without jarring lighting changes.

Obviously there's a lot of work involved to make this into a robust and well-integrated UI3 feature though. On a lot of systems, video availability is sparse and rather unpredictable too (thanks to "Combine or cut"). That makes the problem of finding an appropriate video frame much more difficult.

I'm definitely not saying no to this, but I'm not saying yes either.

Just spitballing a few ideas:

pawel-sw commented 1 year ago
bp2008 commented 1 year ago

intelligently throttling is probably the way to go as I noticed for a long time ranges like 5 mother BI will sometimes return image with text "Opening"

Stuff like that was a major issue in getting the timeline implemented into UI3. Blue Iris delivering seemingly good responses that don't contain the image I asked for :)

Click-and-drag seeking probably will need a special button to preload the range it shouldn't be ad hoc as e.g. a bit more than 5 months of 4k data in my case are 160 images (468MB) Chrome loaded them in about 2.2 minutes in 6 threads, I didn't run into any slowness or memory issue.

Hmm. 468 MB is really big for 160 images, probably your quality is set too high in the Streaming 0 profile. Anyway I need UI3 to be able to run on a wide range of devices, so I would need to test this approach on weak devices with larger numbers of images. We'd be at the mercy of the web browser to efficiently unload hidden images and decode them again from source as needed and honestly I'm not sure if that happens or if I'd need to do it all from script. 160 4K images can fit within memory/video memory on a lot of modern systems. Not so much on an old laptop, cell phone, or smart TV.

UI3 by necessity would need to load these images at much lower quality/resolution, although as you say this could be configurable so that you could get higher quality if you needed it.

2.2 minutes is way too long to wait in my opinion, which is exactly why I would need to load "ad hoc" prioritizing the timestamps nearest the selected time.

I feel that not adding a primary UI tab could hider future development e.g. I just added ChatGPT generated video export which relies on already preloaded images: https://ipcamtalk.com/threads/ad-hoc-timelapse.69178/#post-754672 adding new options and filters would bloat timeline tab

I can appreciate that. If I built this as nothing more than the seeking technique used at wide timeline zoom levels, then a lot of people would never even discover it, and it does not open itself up to further expansion.

FYI your video encode seems to be at 30 FPS while you load images at <= 10 FPS. Also your login code isn't using the biUrl variable.

bp2008 commented 1 year ago

This actually reminds me a lot of my Timelapse project where I have similar goals of making timelapses extremely fast and easy. The UI in that project is frankly only one step up from dogshit right now, as it was designed about 18 years ago with only minimal maintenance done since. The project has gone through many forms over the years but currently it is a Windows service that ingests jpeg images when they appear in specific folders, and organizes them for long term storage. It has vastly more potential than using Blue Iris as the storage backend for timelapse video creation. But I have trouble motivating myself to work on it, as I've never been able to nail down a UI design that I am satisfied with.

bp2008 commented 1 year ago

Did you delete that thread on ipcamtalk? I see it is gone and your user shows 0 posts.

pawel-sw commented 1 year ago

I didn't it shows for me https://ipcamtalk.com/threads/ad-hoc-timelapse.69178/#post-754672

bp2008 commented 1 year ago

Weird, back for me too.