I'm tring to read list of videos from file and show them in ionic components in the form of list with thumbnail of the video file.But thumbnail is not created for each file properly.
videos.ts
import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams, LoadingController, ToastController, PopoverController, AlertController } from 'ionic-angular';
import { DataService } from '../../services/data-service';
import { File } from '@ionic-native/file';
import { VideoPlayer } from '@ionic-native/video-player';
import { VideoEditor } from '@ionic-native/video-editor';
import { SocialSharing } from '@ionic-native/social-sharing';
import { StreamingMedia, StreamingVideoOptions } from '@ionic-native/streaming-media';
@IonicPage()
@Component({
selector: 'page-recent-video',
templateUrl: 'recent-video.html',
})
export class VideosPage {
public videos:any[]=[];
public flag:boolean = false;
public thumb:string;
public videoWithThumb:any[]=[]
constructor(public navCtrl: NavController,
public navParams: NavParams,
public file:File,
public loadingCtrl:LoadingController,
public dataService:DataService,
public videoPlayer:VideoPlayer,
public videoEditor:VideoEditor,
public toastCtrl:ToastController,
public socialShare:SocialSharing,
public popoverCtrl:PopoverController,
public alertCtrl:AlertController,
public mediaPlayer:StreamingMedia ) {
}
ionViewDidLoad() {
console.log('ionViewDidLoad RecentVideoPage');
this.loadVideos()
}
loadVideos(){
if(this.flag == true){
this.videos.splice(0, this.videos.length)
this.videoWithThumb.splice(0, this.videoWithThumb.length)
}else{
this.flag = true
}
const loading = this.loadingCtrl.create({
content:'loading videos..',
duration:2000
})
loading.present()
this.file.listDir(this.file.externalRootDirectory,'FolderName')
.then( dir =>{
for(let dirData of dir)
{
if(dirData.isFile == true && this.fileType(dirData) =='mp4'){
this.storeVideo(dirData.nativeURL, dirData.name )
}
}
loading.dismiss()
})
.catch( err=>{
console.log('reading directory error '+ err)
this.showAlert(err)
})
}
playVideo(item){
let options: StreamingVideoOptions = {
successCallback: () => { console.log('Video played') },
errorCallback: (e) => { console.log('Error streaming') },
orientation: 'portrait'
};
this.mediaPlayer.playVideo(item.url, options);
}
showAlert(msg:string){
const alert = this.alertCtrl.create({
title:'Failed',
subTitle:msg,
buttons:['OK']
})
alert.present()
}
fileType(dirData){
const indexOfLastDot = dirData.nativeURL.lastIndexOf('.');
// const path = dirData.nativeURL.substring(0, indexOfLastDot);
const fileType = dirData.nativeURL.substring(indexOfLastDot + 1);
console.log(fileType)
return fileType
}
storeVideo( url, name ){
this.videos.push({ url:url , name:name })
}
showToast(msg:string){
const toast = this.toastCtrl.create({
message:msg,
duration:2000,
position:'middle'
})
toast.present()
}
}
videos.html
<ion-content padding class="card-background-page">
<!-- webkit-playsinline="webkit-playsinline" -->
<ion-card no-margin margin-bottom class="full-width" overflow-scroll="true"
*ngFor="let item of videos">
<video width="320" height="240" controls="controls"
preload="metadata"
poster= '{{item | createThumbnail}}'
webkit-playsinline="webkit-playsinline"
class="videoPlayer">
<source [src]="item.url" type="video/mp4"/></video>
</ion-card>
<ion-fab right bottom>
<button ion-fab mini color="topBar" tappable (tap)="loadVideos()"><ion-icon name="refresh"></ion-icon></button>
</ion-fab>
</ion-content>
videos.module.ts
import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { VideosPage } from './recent-video';
import { PipesModule } from '../../pipes/pipes.module';
@NgModule({
declarations: [
VideosPage,
],
imports: [
IonicPageModule.forChild(VideosPage),
PipesModule
],
})
export class VideosPageModule {}
**pipe used for creating thumbnail of each item in the list**
create-thumbnail.ts
import { Pipe, PipeTransform } from '@angular/core';
import { VideoEditor } from '@ionic-native/video-editor';
@Pipe({
name: 'createThumbnail',
})
export class CreateThumbnailPipe implements PipeTransform {
public thumb: string;
constructor(public videoEditor:VideoEditor){
}
transform(value: any) {
this.videoEditor.createThumbnail({fileUri:value.url, outputFileName:value.name, atTime:2, width:320, height:240,quality:100} )
.then(ref=>{
console.log(ref)
this.thumb = ref;
// console.log('generated thumb '+ this.thumb )
})
.catch(err=>{
console.log(err)
})
console.log('returning thumb '+ this.thumb)
return this.thumb
}
}
pipe.module.ts
import { NgModule } from '@angular/core';
import { CreateThumbnailPipe } from './create-thumbnail/create-thumbnail';
@NgModule({
declarations: [CreateThumbnailPipe],
imports: [],
exports: [CreateThumbnailPipe]
})
export class PipesModule {}
thumbnail for only fist file is created. For the rest of the video files use the same thumbnail created before please help me to solve this issue.
" Thumbnail for only fist file is created " because you used
Reason-
createThumbnail() -
it take some time to create thumbnail of video but in other side html done its work fast so html pass first url to this function and then this function is busy to make thumbnail of it,but html send all the url to this function but it is still busy so its only create one thumbnail.
Solution -
you must have to make **async** and **await** task or function so that html wait for createThumbnail().so every time html send url to this function then html wait for that function task and then send next url to that function.
here's my code for create thumbnails
async favourite(fileName){
let thumbName = fileName.substr(fileName.lastIndexOf('/') + 1);
const result = await this.commonserviceProvider.thumbUpload(thumbName,fileName); //this service is called for create thumbanils and favourite() function wait for this service
let videoName = fileName.match(/([^\/]+)(?=\.\w+$)/)[0];
const result1 = await this.commonserviceProvider.upload(videoName+".mp4",this.folderPath+videoName+".mp4",1);
this.presentToast('Saved in favourite');
}