Implemented Video Upload and Player (#2)

* Implementing video upload features

* setup image resize processor

* Add video thumbnail with duration and icon

* Fixed issue with video upload timeout and upper case file type on ios

* Added video player page

* Added video player page

* Fixing video player not play on ios

* Added partial file streaming for ios/android video request

* Added nginx as proxy server for better file serving

* update nginx and docker-compose file

* Video player working correctly

* Video player working correctly

* Split duration to the second
This commit is contained in:
Alex
2022-02-06 00:07:56 -06:00
committed by GitHub
parent b6a7d40863
commit 97dc7660b4
32 changed files with 582 additions and 178 deletions

View File

@@ -6,13 +6,13 @@ import { AssetModule } from '../../api-v1/asset/asset.module';
import { AssetService } from '../../api-v1/asset/asset.service';
import { AssetEntity } from '../../api-v1/asset/entities/asset.entity';
import { ImageOptimizeProcessor } from './image-optimize.processor';
import { ImageOptimizeService } from './image-optimize.service';
import { AssetOptimizeService } from './image-optimize.service';
import { MachineLearningProcessor } from './machine-learning.processor';
@Module({
imports: [
BullModule.registerQueue({
name: 'image',
name: 'optimize',
defaultJobOptions: {
attempts: 3,
removeOnComplete: true,
@@ -30,7 +30,7 @@ import { MachineLearningProcessor } from './machine-learning.processor';
TypeOrmModule.forFeature([AssetEntity]),
],
providers: [ImageOptimizeService, ImageOptimizeProcessor, MachineLearningProcessor],
exports: [ImageOptimizeService],
providers: [AssetOptimizeService, ImageOptimizeProcessor, MachineLearningProcessor],
exports: [AssetOptimizeService],
})
export class ImageOptimizeModule {}

View File

@@ -6,9 +6,10 @@ import { AssetEntity } from '../../api-v1/asset/entities/asset.entity';
import sharp from 'sharp';
import fs, { existsSync, mkdirSync } from 'fs';
import { ConfigService } from '@nestjs/config';
import { randomUUID } from 'crypto';
import ffmpeg from 'fluent-ffmpeg';
import { Logger } from '@nestjs/common';
@Processor('image')
@Processor('optimize')
export class ImageOptimizeProcessor {
constructor(
@InjectRepository(AssetEntity) private assetRepository: Repository<AssetEntity>,
@@ -16,8 +17,8 @@ export class ImageOptimizeProcessor {
private configService: ConfigService,
) {}
@Process('optimize')
async handleOptimization(job: Job) {
@Process('resize-image')
async resizeUploadedImage(job: Job) {
const { savedAsset }: { savedAsset: AssetEntity } = job.data;
const basePath = this.configService.get('UPLOAD_LOCATION');
@@ -58,4 +59,32 @@ export class ImageOptimizeProcessor {
return 'ok';
}
@Process('get-video-thumbnail')
async resizeUploadedVideo(job: Job) {
const { savedAsset, filename }: { savedAsset: AssetEntity; filename: String } = job.data;
const basePath = this.configService.get('UPLOAD_LOCATION');
// const resizePath = savedAsset.originalPath.replace('/original/', '/thumb/');
console.log(filename);
// Create folder for thumb image if not exist
const resizeDir = `${basePath}/${savedAsset.userId}/thumb/${savedAsset.deviceId}`;
if (!existsSync(resizeDir)) {
mkdirSync(resizeDir, { recursive: true });
}
ffmpeg(savedAsset.originalPath)
.thumbnail({
count: 1,
timestamps: [1],
folder: resizeDir,
filename: `${filename}.png`,
})
.on('end', async (a) => {
await this.assetRepository.update(savedAsset, { resizePath: `${resizeDir}/${filename}.png` });
});
return 'ok';
}
}

View File

@@ -2,17 +2,15 @@ import { InjectQueue } from '@nestjs/bull';
import { Injectable } from '@nestjs/common';
import { Queue } from 'bull';
import { randomUUID } from 'crypto';
import { join } from 'path';
import { AssetEntity } from '../../api-v1/asset/entities/asset.entity';
import { AuthUserDto } from '../../decorators/auth-user.decorator';
@Injectable()
export class ImageOptimizeService {
constructor(@InjectQueue('image') private imageQueue: Queue) {}
export class AssetOptimizeService {
constructor(@InjectQueue('optimize') private optimizeQueue: Queue) {}
public async resizeImage(savedAsset: AssetEntity) {
const job = await this.imageQueue.add(
'optimize',
const job = await this.optimizeQueue.add(
'resize-image',
{
savedAsset,
},
@@ -23,4 +21,19 @@ export class ImageOptimizeService {
jobId: job.id,
};
}
public async getVideoThumbnail(savedAsset: AssetEntity, filename: String) {
const job = await this.optimizeQueue.add(
'get-video-thumbnail',
{
savedAsset,
filename,
},
{ jobId: randomUUID() },
);
return {
jobId: job.id,
};
}
}