An open API service indexing awesome lists of open source software.

https://github.com/janeliascicomp/videoannotation


https://github.com/janeliascicomp/videoannotation

Last synced: 8 months ago
JSON representation

Awesome Lists containing this project

README

          

## Quick Start

We will use ***React, Next.js*** and our library to create a simple video annotation web like this:

![demo_page2_081524.png](/public/demo_page2_081524.png)

If you’re new to React or Next.js, check out [React](https://react.dev/learn) and [Next.js](https://nextjs.org/learn/foundations/about-nextjs).

### Step 1: Initialize a new project

First of all, you need to install [Node.js](https://nodejs.org/en/) (>=19.0.0).

Then clone this repo.

Then outside of the repo dir, run
```bash
npx create-next-app@13.2.4 # The version used to create the page
```

Answer the popup questions. For my test, I used these settings. You can also customize your own.

![nextjs_settings.png](/public/nextjs_settings.png)

### Step 2: Copy our library to your project and install dependencies

> [!NOTE]
> This step will be replaced by `npm install ourLib` after we release this library

Copy ***package.json, components, utils*** and ***styles*** folders from the repo dir to the root dir of the project you just created.

In the root dir of your project, install the dependencies.
```bash
npm install
```

### Step 3: Run the development server

```bash
npm run dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

### Step 4: Modify `pages/index.js`
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.

For the web in the image above, the index.js file should look like this

```javascript
import React, {useState} from 'react';
import Head from 'next/head';
import Workspace from '../components/Workspace.js';
import Canvas from '../components/Canvas.js';
import VideoUploader from '../components/VideoUploader.js';
import BtnContainer from '../components/BtnContainer.js';
import AnnotationTable from '../components/AnnotationTable.js';
import DownloadBtn from '../components/DownloadBtn.js';
import ProjectManager from '../components/ProjectManager.js';
import ModalJsonUploader from '../components/ModalJsonUploader.js';
import VideoManager from '../components/VideoManager.js';
import CanvasAdditionalDataController from '../components/CanvasAdditionalDataController.js';
import DropdownMenu from '../components/DropdownMenu.js';
import ProjectList from '../components/ProjectList.js';
import SaveAnnotationBtn from '../components/SaveAnnotationBtn.js';
import InfoBar from '../components/InfoBar.js';
import {Row, Col} from 'react-bootstrap'; // Third party components. Refer to the tutorial on https://react-bootstrap.netlify.app/docs/layout/grid
import { Menu, Modal } from 'antd'; // Third party components. Refer to the tutorial on https://ant.design/components/menu, and https://ant.design/components/modal
import { drawCircle, drawLine } from '../utils/canvasUtils.js'; // canvasUtils.js is a wrapper of fabric.js. It provides functions to operate on canvas easily. Currently, only these two functions are provided.

// Client side components. They cannot be rendered on the server side, thus need to be explicitly marked as client side comp.
import dynamic from 'next/dynamic';

const AdditionalDataChart = dynamic(() => import('../components/AdditionalDataChart.js'), { ssr: false });
const AnnotationChart = dynamic(() => import('../components/AnnotationChart.js'), { ssr: false });

export default function Home() {
// The ..open/set..Open states are to allow the child modal components to control the visibility of themselves inside.
const [newProjectManagerOpen, setNewProjectManagerOpen] = useState(false);
const [editProjectManagerOpen, setEditProjectManagerOpen] = useState(false);
const [configUploaderOpen, setConfigUploaderOpen] = useState(false);
const [projectListOpen, setProjectListOpen] = useState(false);
const [videoManagerOpen, setVideoManagerOpen] = useState(false);
const [annotationUploaderOpen, setAnnotationUploaderOpen] = useState(false);
const [canvasAdditionalDataControllerOpen, setCanvasAdditionalDataControllerOpen] = useState(false);
const [info, setInfo] = useState(''); // To display feedback info

const projectDropdownItems = [
{
label: 'Exisiting Projects',
compName: 'ProjectList', // When pass a component, it is required to have a compName prop whose value should be equivalent to the name of the component, e.g. 's compName is 'ProjectList'.
component: ,
// preventDefault: true, // when use some built-in components as the children of DropdownMenu, there may be some pre-defined behaviors, such as opening a modal window. To prevent the default behavior, set this to true.
},
{
label: 'New Project',
compName: 'ProjectManager',
component: ,
},
{
label: 'Upload Project',
compName: 'ModalJsonUploader',
component: ,
},
{
label: 'Edit Project',
compName: 'ProjectManager',
component: ,
},
{
label: 'Download Configuration',
compName: 'DownloadBtn',
component: ,
},
];

function projectDropdownClickHandler(e) {
/**
* Click event handler for DropdownMenu. Will be called after the default behavior of each child.
* e is the event object which has a key property corresponding to the index(integer) of each child in the 'menu' prop. This may be different with the 'key' prop of the component passed to each child.
* */
// console.log(e);
// TODO: customize click handler

// const label = projectDropdownItems[e.key].label;
// switch (label) {
// case 'Exisiting Projects':
// setInfo('Exisiting Projects');
// break;
// case 'New Project':
// setInfo('New Project');
// break;
// case 'Upload Project':
// setInfo('Upload Project');
// break;
// case 'Save Annotation':
// setInfo('Save Annotation');
// break;
// case 'Edit Project':
// setInfo('Edit Project');
// break;
// case 'Download Configuration':
// setInfo('Download Configuration');
// break;
// }
}

const projectDropdown = ;

const videoDropdownItems = [
{
label: 'Video Manager',
compName: 'VideoManager',
component: setVideoManagerOpen(false)}
style={{overflowX: 'auto'}}
footer={null}
>

,
},
{
label: 'Additional Data For Canvas',
compName: 'CanvasAdditionalDataController',
component: setCanvasAdditionalDataControllerOpen(false)}
style={{overflowX: 'auto'}}
footer={null}
>

,
},
];

function drawDataAsCircle(params) {
/**
* OnLoad event handler for the additional data for canvas.
*
* params: {
* target: fabric obj needed for the drawing. Just pass it to the imported func from canvasUtils.js
* data: [additional data in needed range]
* }
*/
for (let c of params.data) {
c.push(3); // add radius
drawCircle(params.target, c, 'red');
}
}

function drawDataAsLine(params) {
for (let l of params.data) {
drawLine(params.target, l, 'white');
}

}

function videoDropdownClickHandler(e) {
// TODO: customize click handler
}

const videoDropdown =

const annotationDropdownItems = [
{
label: 'Save Annotation',
compName: 'SaveAnnotationBtn',
component: ,
},
{
label: 'Download Annotation',
compName: 'DownloadBtn',
component: ,
},
{
label: 'Upload Annotation',
compName: 'ModalJsonUploader',
component: ,
},
];

function annotationDropdownClickHandler(e) {
// TODO: customize click handler
}

const annotationDropdown =

const menubarItems = [
{
label: projectDropdown,
key: '0',
},
{
label: videoDropdown,
key: '1',
},
{
label: annotationDropdown,
key: '2',
},
]

return (



Annotator




{/* If state info is null, InfoBar will only display predefined information for events. Otherwise, will display both predefined and contents of the info state */}






















)
}

```

> [!NOTE]
> In order to process the video, you need to set up a backend server. We will cover this in another [repo](https://github.com/JaneliaSciComp/videoAnnotation_backend/tree/main).

Here we used react-bootstrap for the layout. Check out the [tutorial](https://react-bootstrap.netlify.app/docs/layout/grid), and also [Ant Design](https://ant.design/components)'s components.