Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RSDK-8647 - Add save do_command #6

Closed
wants to merge 27 commits into from
Closed

RSDK-8647 - Add save do_command #6

wants to merge 27 commits into from

Conversation

seanavery
Copy link
Collaborator

@seanavery seanavery commented Sep 3, 2024

Description

  • Adds FFmpeg configure flags for static build to support concat demuxing of mp4 files.
  • Adjusts module configuration to match latest tech spec details.
  • Adds a concater struct to handle FFmpeg concat demuxer runtime.
    • Handles writing/clearing temprorary concat.txt file used for demuxer configuration.
    • Handles copying codec configuration from input.
    • Adjusts frame timestamps to satisfy a single continuous video.
  • Adds interface and validation for save do_command.
  • Adds helpers to match save queries with available storage files.

This PR does not include encoder, segmeneter, and deleter code in the diff.

This contains a simple datetime matcher for storage files. Will need to follow up with a more advanced demxuer that can handle file trimming.

Open to comments/reviews on non-diffed code. Reviewers can expand the encoder.go, segmenter.go, and cam.go files in the Files Changed tab for full context.

Refs

Test

  • From/To requests outside of storage range fail with error ✅
  • From/To requests inside storage range are successful ✅
  • From/To requests with invalid date-time format error ✅
  • Concated video files are playable ✅
  • Save do_command response contains uploaded file name ✅

Tests were run with a webcam source and the following config:

{
  "components": [
    {
      "name": "wc-cam",
      "namespace": "rdk",
      "type": "camera",
      "model": "webcam",
      "attributes": {
        "height_px": 480,
        "frame_rate": 25,
        "format": "YUYV",
        "video_path": "/dev/video0",
        "width_px": 640
      }
    },
    {
      "name": "video-store",
      "namespace": "rdk",
      "type": "camera",
      "model": "seanavery:video:storage",
      "attributes": {
        "storage": {
          "segment_seconds": 30,
          "size_gb": 100
        },
        "video": {
          "preset": "medium",
          "format": "mp4",
          "codec": "h264",
          "bitrate": 1000000
        },
        "cam_props": {
          "framerate": 25,
          "width": 640,
          "height": 480
        },
        "camera": "wc-cam",
        "vision": "vision-1"
      },
      "depends_on": [
        "wc-cam"
      ]
    }
  ],
  "services": [
    {
      "name": "data_manager-1",
      "namespace": "rdk",
      "type": "data_manager",
      "attributes": {
        "capture_dir": "",
        "tags": [],
        "additional_sync_paths": [],
        "capture_disabled": true,
        "sync_interval_mins": 0.1
      }
    }
  ],
  "modules": [
    {
      "type": "local",
      "name": "video-storage",
      "executable_path": "/home/viam/video-store",
      "log_level": "debug"
    }
  ]
}

Example save command:

{
  "command": "save",
  "from": "2024-08-29_16-32-44",
  "to": "2024-08-29_17-08-48",
  "metadata": "person-detector_person1-0.96"
}

Response:

{
  "command": "save",
  "file": "video-store-1_2024-08-29_16-32-44_person-detector_person1-0.96.mp4"
}

@hexbabe
Copy link
Collaborator

hexbabe commented Sep 4, 2024

Should we review POC first?

@seanavery seanavery changed the title Save cmd RSDK-8147 - Add save do_command Sep 4, 2024
@seanavery
Copy link
Collaborator Author

Should we review POC first?
@hexbabe Will resubmit this PR against an empty ref for full context of the code in review.

Copy link

@randhid randhid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to be a giant model, I like how you're broken out the file into concater and segmented, can I request that we break out the setup functionality (registration, validation, creator and close) into it's own file too?

I would like to add tests at this point to lock in some of your utils and Validation functionality.

I will look at cam.go in a separate review.

@@ -19,37 +19,43 @@ import (
)

// Model is the model for the video storage camera component.
// TODO(seanp): Personal module for now, should be movied to viam module in prod.
// TODO(seanp): Personal module for now, should be moved to viam module in prod.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's in viam-modules now.

uploadPath string
name resource.Name
conf *Config
logger logging.Logger

cam camera.Camera
stream gostream.VideoStream

workers rdkutils.StoppableWorkers
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you bump rdk, which I suggest you do you'll hae to get this from goutils goutils.NewBackgroudnWorkers is the creator function.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched to latest NewBackgroundWorkes in goutils.

"storage": {
"clip_seconds": 30,
"segment_seconds": 30,
"size_gb": 100
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the save DoCommand have an optional directory for video storage and sync upload?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not in do_command, those are optional attrs in the module - will include it in the README example.

"additional_sync_paths": [
"/home/viam/.viam/video-upload/"
],
"additional_sync_paths": [],
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call out that this is custom, as stated in the scope, right now there's no clue as to why this is int he example config.

defaultStoragePath = ".viam/video-storage"

defaultLogLevel = "info"
deleterInterval = 60 // seconds
)

type videostore struct {
resource.AlwaysRebuild
resource.TriviallyCloseable
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have a Close implemented, which is what I expect since we're going on and on on a loop saving video. You can delete this line, which just returns nil when you call close.

Suggested change
resource.TriviallyCloseable

ffmppegLogLevel(logLevel)

// Create encoder to handle encoding of frames.
// TODO(seanp): Forcing h264 for now until h265 is supported.
if newConf.Video.Codec != "h264" {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's premptively factor this into an enum.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, added enum+handlers for codec type.

@@ -138,7 +144,6 @@ func newvideostore(
if newConf.Video.Format == "" {
newConf.Video.Format = defaultVideoFormat
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the pattern of

s.thingy = defaultThingy
if newConf.Thingy != nil/empty{
    s.thingy = newConf.Thingy
}

But it might be messy here unless you make a new encoder with the logger first. You can also move this logic to the newSegmenter and newEncoder functions since you're passing in the config variables anyway.

@@ -19,37 +19,43 @@ import (
)

// Model is the model for the video storage camera component.
// TODO(seanp): Personal module for now, should be movied to viam module in prod.
// TODO(seanp): Personal module for now, should be moved to viam module in prod.
var Model = resource.ModelNamespace("seanavery").WithFamily("video").WithModel("storage")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's okay to use the viam namespace, it's also okay to transfer a release later, just try to only upload release candidates to the registry for now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, moved to viam namespace

}
return matchedFiles
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add some test coverage for correctly formatting these filenames at this point. That's a good thing to check on and will test your utils, which are all helper functions that should not change much. It will also allow you to test out some weird user config silliness.

vs.seg.Close()
vs.enc.close()
vs.seg.close()
vs.conc.close()
return nil
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see validation logic for the data manager being present in the configuration anywhere unless I missed it; that is part of the scope. However, I think that should be a separate ticket, I don't seeit mentioned in the epic's current tasks.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call - still need to add this. May need to amend the scope doc to include the data manager service as a mandatory dependency in the config.

@hexbabe
Copy link
Collaborator

hexbabe commented Sep 10, 2024

I don't need to review this right? Looks like a lot of iterations have been made since this in the other PR

@randhid
Copy link

randhid commented Sep 10, 2024

I don't need to review this right? Looks like a lot of iterations have been made since this in the other PR

@seanavery please close this.

@seanavery seanavery closed this Sep 10, 2024
@seanavery seanavery changed the title RSDK-8147 - Add save do_command RSDK-8647 - Add save do_command Sep 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants