Add CI Workflow
This commit is contained in:
29
index.js
29
index.js
@@ -6,15 +6,17 @@ const path = require('path');
|
|||||||
const cors = require('cors');
|
const cors = require('cors');
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
|
|
||||||
|
const BASE_PATH = `/data`;
|
||||||
|
const OUTPUT_PATH = `${BASE_PATH}/output`;
|
||||||
|
const TMP_PATH = `${BASE_PATH}/tmp`;
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const port = 3000;
|
const port = 3000;
|
||||||
|
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
|
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
|
|
||||||
// Configuration de la file d'attente Bull
|
const videoQueue = new Queue('crawlflix_queue', 'redis://192.168.1.222:32768');
|
||||||
const videoQueue = new Queue('crawl', 'redis://192.168.1.222:32768');
|
|
||||||
|
|
||||||
videoQueue.on('error', (e) => {
|
videoQueue.on('error', (e) => {
|
||||||
console.log('An error occured', e);
|
console.log('An error occured', e);
|
||||||
@@ -60,7 +62,6 @@ const runProgressCommand = (command) => {
|
|||||||
if (!perc) {
|
if (!perc) {
|
||||||
process.stdout.write(data.toString());
|
process.stdout.write(data.toString());
|
||||||
} else {
|
} else {
|
||||||
//console.log('🐳 Percentage ====> ' + perc);
|
|
||||||
emitter.emit('percentage', perc);
|
emitter.emit('percentage', perc);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -165,6 +166,8 @@ videoQueue.process((job) => {
|
|||||||
const { mp4Filename, mpdUrl, keys, wantedResolution } = job.data;
|
const { mp4Filename, mpdUrl, keys, wantedResolution } = job.data;
|
||||||
const downloaderPath = path.join(process.env.HOME, 'Downloads/N_m3u8DL-RE_Beta_osx-arm64/N_m3u8DL-RE');
|
const downloaderPath = path.join(process.env.HOME, 'Downloads/N_m3u8DL-RE_Beta_osx-arm64/N_m3u8DL-RE');
|
||||||
const mp4decryptPath = path.join(process.env.HOME, 'Downloads/Bento4-SDK-1-6-0-641.universal-apple-macosx/bin/mp4decrypt');
|
const mp4decryptPath = path.join(process.env.HOME, 'Downloads/Bento4-SDK-1-6-0-641.universal-apple-macosx/bin/mp4decrypt');
|
||||||
|
const mp4TmpFilepath = path.join(TMP_PATH, `${mp4Filename}.mp4`);
|
||||||
|
const mp4FinalFilepath = path.join(OUTPUT_PATH, `${mp4Filename}.mp4`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const filesExist = await checkFilesExistance('encrypted');
|
const filesExist = await checkFilesExistance('encrypted');
|
||||||
@@ -180,7 +183,7 @@ videoQueue.process((job) => {
|
|||||||
}[wantedResolution] || [1920, 1080];
|
}[wantedResolution] || [1920, 1080];
|
||||||
console.log('Encrypted files not found, downloading...');
|
console.log('Encrypted files not found, downloading...');
|
||||||
job.progress(10);
|
job.progress(10);
|
||||||
const { executeCommand, emitter } = runProgressCommand(`${downloaderPath} \"${mpdUrl}\" --save-name ${mp4Filename}_encrypted --select-video \"(?=.*${resPattern[0]})(?=.*${resPattern[1]})\" --select-audio lang=\"fr|en\":for=best2 --select-subtitle all`, true);
|
const { executeCommand, emitter } = runProgressCommand(`${downloaderPath} \"${mpdUrl}\" --save-name ${mp4TmpFilepath}_encrypted --select-video \"(?=.*${resPattern[0]})(?=.*${resPattern[1]})\" --select-audio lang=\"fr|en\":for=best2 --select-subtitle all`, true);
|
||||||
emitter.on('percentage', (percentage) => {
|
emitter.on('percentage', (percentage) => {
|
||||||
console.log(`Download Progression : ${percentage}%`);
|
console.log(`Download Progression : ${percentage}%`);
|
||||||
job.progress(Math.round(10 + (percentage / 5)));
|
job.progress(Math.round(10 + (percentage / 5)));
|
||||||
@@ -193,7 +196,7 @@ videoQueue.process((job) => {
|
|||||||
job.progress(30);
|
job.progress(30);
|
||||||
|
|
||||||
// Décryptage vidéo
|
// Décryptage vidéo
|
||||||
await runCommand(`${mp4decryptPath} ${keys.map(k => `--key ${k.key}:${k.value}`).join(' ')} "${mp4Filename}_encrypted.mp4" "${mp4Filename}_decrypted.mp4"`);
|
await runCommand(`${mp4decryptPath} ${keys.map(k => `--key ${k.key}:${k.value}`).join(' ')} "${mp4TmpFilepath}_encrypted.mp4" "${mp4TmpFilepath}_decrypted.mp4"`);
|
||||||
|
|
||||||
job.progress(50);
|
job.progress(50);
|
||||||
|
|
||||||
@@ -201,7 +204,7 @@ videoQueue.process((job) => {
|
|||||||
const audioFiles = await fs.readdir('.');
|
const audioFiles = await fs.readdir('.');
|
||||||
const finalAudio = [];
|
const finalAudio = [];
|
||||||
for (const file of audioFiles) {
|
for (const file of audioFiles) {
|
||||||
if (file.startsWith(`${mp4Filename}_encrypted`) && file.endsWith('.m4a')) {
|
if (file.startsWith(`${mp4TmpFilepath}_encrypted`) && file.endsWith('.m4a')) {
|
||||||
const baseName = path.basename(file, '.m4a');
|
const baseName = path.basename(file, '.m4a');
|
||||||
await runCommand(`${mp4decryptPath} ${keys.map(k => `--key ${k.key}:${k.value}`).join(' ')} "${file}" "${baseName}_decrypted.m4a"`);
|
await runCommand(`${mp4decryptPath} ${keys.map(k => `--key ${k.key}:${k.value}`).join(' ')} "${file}" "${baseName}_decrypted.m4a"`);
|
||||||
finalAudio.push(`${baseName}_decrypted.m4a`);
|
finalAudio.push(`${baseName}_decrypted.m4a`);
|
||||||
@@ -211,7 +214,7 @@ videoQueue.process((job) => {
|
|||||||
job.progress(70);
|
job.progress(70);
|
||||||
|
|
||||||
// Combinaison avec ffmpeg
|
// Combinaison avec ffmpeg
|
||||||
let ffmpegCommand = `ffmpeg -y -i ${mp4Filename}_decrypted.mp4`;
|
let ffmpegCommand = `ffmpeg -y -i ${mp4TmpFilepath}_decrypted.mp4`;
|
||||||
let mapCommand = ' -map 0:v';
|
let mapCommand = ' -map 0:v';
|
||||||
let inputIndex = 1;
|
let inputIndex = 1;
|
||||||
|
|
||||||
@@ -223,7 +226,7 @@ videoQueue.process((job) => {
|
|||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
ffmpegCommand += `${mapCommand} -c copy ${mp4Filename}.mp4`;
|
ffmpegCommand += `${mapCommand} -c copy ${mp4FinalFilepath}.mp4`;
|
||||||
await runCommand(ffmpegCommand);
|
await runCommand(ffmpegCommand);
|
||||||
|
|
||||||
job.progress(90);
|
job.progress(90);
|
||||||
@@ -231,17 +234,17 @@ videoQueue.process((job) => {
|
|||||||
// Renommage des fichiers SRT
|
// Renommage des fichiers SRT
|
||||||
let counter = 1;
|
let counter = 1;
|
||||||
for (const file of audioFiles) {
|
for (const file of audioFiles) {
|
||||||
if (file.startsWith(`${mp4Filename}_encrypted`) && file.endsWith('.srt')) {
|
if (file.startsWith(`${mp4TmpFilepath}_encrypted`) && file.endsWith('.srt')) {
|
||||||
await fs.rename(file, `${mp4Filename}_${counter}.srt`);
|
await fs.rename(file, `${mp4FinalFilepath}_${counter}.srt`);
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nettoyage (commenté pour correspondre au script original)
|
// Nettoyage (commenté pour correspondre au script original)
|
||||||
await runCommand(`rm ${mp4Filename}_encrypted* && rm ${mp4Filename}_decrypted*`);
|
await runCommand(`rm ${mp4TmpFilepath}_encrypted* && rm ${mp4TmpFilepath}_decrypted*`);
|
||||||
|
|
||||||
job.progress(100);
|
job.progress(100);
|
||||||
resolve({ message: `File fetched and decrypted with success: ${mp4Filename}.mp4`, filePath: `${mp4Filename}.mp4`, fileName: `${mp4Filename}.mp4` });
|
resolve({ message: `File fetched and decrypted with success: ${mp4Filename}.mp4`, filePath: `${mp4FinalFilepath}.mp4`, fileName: `${mp4Filename}.mp4` });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('Error while processing task', error)
|
console.log('Error while processing task', error)
|
||||||
reject(new Error(`${error.toString() || error}`));
|
reject(new Error(`${error.toString() || error}`));
|
||||||
|
|||||||
60
workflows/ci.yaml
Normal file
60
workflows/ci.yaml
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
name: ci
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: ${{ vars.DOCKER_REGISTRY_URL }}
|
||||||
|
IMAGE_NAME: bertomlab/crawlflix-api
|
||||||
|
IMAGE_TAG: ${{ github.sha }}
|
||||||
|
CONTAINER_NAME: ${{ vars.CONTAINER_NAME }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
Image build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
with:
|
||||||
|
config-inline: |
|
||||||
|
[registry."${{ env.REGISTRY }}"]
|
||||||
|
http = true
|
||||||
|
|
||||||
|
- name: Login to Docker Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ vars.DOCKER_REGISTRY_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
platforms: linux/amd64
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}
|
||||||
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||||
|
|
||||||
|
- name: Inspect
|
||||||
|
run: |
|
||||||
|
docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}
|
||||||
|
Deployment:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Deploy to server
|
||||||
|
uses: appleboy/ssh-action@master
|
||||||
|
with:
|
||||||
|
host: ${{ vars.SERVER_HOST }}
|
||||||
|
username: ${{ vars.SERVER_USERNAME }}
|
||||||
|
key: ${{ secrets.SERVER_SSH_KEY }}
|
||||||
|
envs: REGISTRY,IMAGE_NAME,IMAGE_TAG
|
||||||
|
script: |
|
||||||
|
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}
|
||||||
|
docker stop ${{ env.CONTAINER_NAME }} || true
|
||||||
|
docker rm ${{ env.CONTAINER_NAME }} || true
|
||||||
|
docker run -d --name ${{ env.CONTAINER_NAME }} ${{ vars.CONTAINER_EXTRA }} -p ${{ vars.CONTAINER_EXTERNAL_PORT }}:${{ vars.CONTAINER_INTERNAL_PORT }} ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}
|
||||||
Reference in New Issue
Block a user