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

Enhancement: Improve Access to Recorded Videos by Organizing Saved Files #1876

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions backup/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Jitsi Video Organizer

This script is designed to help administrators and users of Jitsi who are running the service in Docker to easily manage and access recorded conference videos. The script automatically organizes the videos by renaming folders that are created for each video into more descriptive names and moving them to a structured directory.

## Features

- Renames videos to descriptive names based on conference names and timestamps.
- Moves recorded videos to a more accessible directory structure.
- Logs the actions performed for easy tracking and troubleshooting.

## Prerequisites

- A directory where you can mount it to your Docker.
- Jitsi installed and running in Docker.
- Access to the file system where Jitsi stores recorded videos.
- Access to backup directory where you need to move your recorded videos.
- A CronJob for executing script in case you need to have a frequent execution process.


## Configuration

Open the script "main.go" and configure the following variables:

- srcDir: The directory where Jitsi stores recorded videos. This should be the directory mounted on your Docker container.
- dstDir: The destination directory where you want to move the organized videos.
- videoLog: The file path where the script will log its actions.

**Variables available to change:**
```bash
srcDir = "/path/to/your/mounted/jitsi/recordings"

dstDir = "/path/to/your/organized/videos"

videoLog = "/path/to/your/log/file.log"
```

## Setup

**Clone the Repository:**

```bash
git clone [email protected]:jitsi/docker-jitsi-meet.git

cd docker-jitsi-meet/backup

go build -o "Name Your Script Here" .
```

## Running the Script Manually

**After you've built the script, you can run the script manually to organize your videos:**
```bash
go build -o "Name Your Script Here" .

./"Your Executable Script"
```
This will rename the videos and move them from folders to the destination directory.

## Automation with CronJob
To automate the process of organizing recorded videos, you can set up a cron job on your server. This allows the script to run at defined intervals, ensuring that your videos are always organized.

**Open your crontab:**

```bash
crontab -e

Add the following line to schedule the script to run at a specific time. For example, to run the script every day at midnight:

0 0 * * * user /path/to/your/script/organize_videos
```
Make sure to replace the path with the actual path to your script.


3 changes: 3 additions & 0 deletions backup/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module jitsi-videos

go 1.22.6
137 changes: 137 additions & 0 deletions backup/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package main

import (
"crypto/sha256"
"fmt"
"io"
"log"
"os"
"path/filepath"
"strings"
)

const (
srcDir = "/srv/recordings/"
dstDir = "/srv/record/"
videoLog = "/srv/record/logfile.log"
)

func calculateHashSum(filePath string) (string, error) {
file, err := os.Open(filePath)
if err != nil {
return "", err
}
defer file.Close()

hash := sha256.New()
if _, err := io.Copy(hash, file); err != nil {
return "", err
}
return fmt.Sprintf("%x", hash.Sum(nil)), nil

}

func checkMetadataExist(dir string) bool {
metadataPath := filepath.Join(dir, "metadata.json")
_, err := os.Stat(metadataPath)
return !os.IsNotExist(err)
}

func copyFiles(src, dst string) error {
srcFile, err := os.Open(src)
if err != nil {
return err
}
defer srcFile.Close()

dstFile, err := os.Create(dst)
if err != nil {
return err
}
defer dstFile.Close()

_, err = io.Copy(dstFile, srcFile)
if err != nil {
return err
}

srcInfo, err := srcFile.Stat()
if err != nil {
return err
}
return os.Chmod(dst, srcInfo.Mode())

}

func main() {
var directoriesToRemove []string

err := filepath.Walk(srcDir,
func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
metaPath := filepath.Dir(path)
if checkMetadataExist(metaPath) {
fileName := info.Name()
fileParts := strings.Split(fileName, "_")
if len(fileParts) > 1 {
newFileName := fileParts[0] + filepath.Ext(fileName)
newPath := filepath.Join(dstDir, newFileName)
if _, err := os.Stat(newPath); err == nil {
srcHash, err := calculateHashSum(path)
if err != nil {
return err
}

dstHash, err := calculateHashSum(newPath)
if err != nil {
return err

}
if srcHash == dstHash {

fmt.Printf("File already Exist and has been removed, skipping: %s\n", metaPath)
return nil
}
} else {
err := copyFiles(path, newPath)
if err != nil {
return err
}

logFile, err := os.OpenFile(videoLog, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
log.Fatal(err)
}

defer logFile.Close()

log.SetOutput(logFile)

log.Printf("Copied: %s -> %s\n", path, newPath)

}
}

directoriesToRemove = append(directoriesToRemove, metaPath)
}

}
return err
})

if err != nil {
fmt.Printf("Error: %v\n", err)
}

for _, pathsToRemove := range directoriesToRemove {
os.RemoveAll(pathsToRemove)
if err != nil {
fmt.Printf("Error removing directory %s: %v\n", pathsToRemove, err)
} else {
fmt.Printf("Removed directory: %s\n", pathsToRemove)
}
}
}