Movido funciones para extraer fotograma a Conversor. Ya se extrae el fotograma…

Movido funciones para extraer fotograma a Conversor. Ya se extrae el fotograma seleccionado del vídeo
parent 2c62c397
...@@ -2,27 +2,33 @@ import 'dart:io'; ...@@ -2,27 +2,33 @@ import 'dart:io';
import 'package:ffmpeg_kit_flutter_new/ffmpeg_kit.dart'; import 'package:ffmpeg_kit_flutter_new/ffmpeg_kit.dart';
import 'package:ffmpeg_kit_flutter_new/ffmpeg_session.dart'; import 'package:ffmpeg_kit_flutter_new/ffmpeg_session.dart';
import 'package:ffmpeg_kit_flutter_new/ffprobe_kit.dart';
import 'package:ffmpeg_kit_flutter_new/return_code.dart'; import 'package:ffmpeg_kit_flutter_new/return_code.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:prueba_multimedia/modelo/modelo.dart'; import 'package:prueba_multimedia/modelo/modelo.dart';
// TODO: TERMINAR
abstract class Conversor { abstract class Conversor {
/// Se llama una vez el usuario pulsa convertir /// Se llama una vez el usuario pulsa convertir
static Future<ReturnCode?> convertir(Archivo archivo, String pathSalida) async { static Future<ReturnCode?> convertir(Archivo archivo, String pathSalida) async {
String path = archivo.file.path; String path = archivo.file.path;
ReturnCode? returnCode;
String nuevoPath = "$pathSalida/${archivo.nombre}.${archivo.formatoDestino!.name}"; String nuevoPath = "$pathSalida/${archivo.nombre}.${archivo.formatoDestino!.name}";
String comando = "-i $path $nuevoPath";
FFmpegSession session = await FFmpegKit.execute(comando); // TODO: REVISAR EL SACAR FOTOGRAMA. NO PARECE SALIR NADA
ReturnCode? returnCode = await session.getReturnCode(); bool conversionVideoAOtro =
archivo.formatoOriginal.tipoMultimedia == TipoMultimedia.video
&& archivo.formatoDestino?.tipoMultimedia != TipoMultimedia.video;
if (!conversionVideoAOtro) {
returnCode = await FFmpegKit.execute("-i $path $nuevoPath")
.then((session) => session.getReturnCode());
} else {
returnCode = await Conversor.getFotograma(archivo, archivo.fotograma!, nuevoPath);
}
return returnCode; return returnCode;
} }
// https://www.ffmpeg.org/ffmpeg-formats.html#ffmetadata // https://www.ffmpeg.org/ffmpeg-formats.html#ffmetadata
/// Devuelve los metadatos del archivo o null si ha habido un problema /// Devuelve los metadatos del archivo o null si ha habido un problema
static Future<List<Metadato>> getMetadatos(Archivo archivo) async { static Future<List<Metadato>> getMetadatos(Archivo archivo) async {
// Creamos archivo metadatos // Creamos archivo metadatos
...@@ -63,4 +69,56 @@ abstract class Conversor { ...@@ -63,4 +69,56 @@ abstract class Conversor {
return metadatos; return metadatos;
} }
static Future<int?> getNumFotogramas(Archivo archivo) async {
String? sNumFotogramas = await (FFprobeKit.execute(
'-v error -select_streams v:0 -count_frames -show_entries stream=nb_read_frames -of csv=p=0 -i ${archivo.file.path}'
).then((session) => session.getOutput()));
return sNumFotogramas != null
? int.tryParse(sNumFotogramas)
: null;
}
static Future<double?> getDuracionVideo(Archivo archivo) async {
String? sDuracion = await FFprobeKit.execute(
'-v 0 -of csv="p=0" -select_streams V:0 -show_entries stream=duration -i ${archivo.file.path}'
).then((session) => session.getOutput());
return sDuracion != null
? double.tryParse(sDuracion)
: null;
}
/// Extrae el fotograma especificado con un timestamp de un video.
/// Devuelve un archivo que es una imagen jpg
// Podría hacer que los parámetros fueran números pero se quedó así
static Future<ReturnCode?> getFotograma(Archivo video, int fotograma, [String? salida]) async {
// Cálculo de la timestamp del fotograma a extraer
int? numFotogramas = await Conversor.getNumFotogramas(video);
double? duracion = await Conversor.getDuracionVideo(video);
// Los timestamp son de la forma 00:00:00 y podemos tener segundos con decimales
final double timeStamp = (fotograma/numFotogramas!)*duracion!;
String hour, min, sec;
sec = ((timeStamp % 60.0) % 60.0).toString();
while(sec.indexOf('.') < 2){
sec = '0$sec';
}
min = ((timeStamp / 60).floor() % 60).toString();
min = min.padLeft(2,'0');
hour = (timeStamp / 3600).floor().toString();
hour = hour.padLeft(2,'0');
// Extraer el fotograma
final directory = await getApplicationSupportDirectory();
String pathSalida = salida ?? '${directory.absolute.path}${Platform.pathSeparator}fotograma.${video.formatoDestino?.extension}';
// Este comando extrae un frame del timestamp dado
// La opción -y acepta hacer overwrite
return await FFmpegKit.execute(
'-y -i ${video.file.path} -ss $hour:$min:$sec -frames:v 1 $pathSalida'
).then((session) => session.getReturnCode());
}
} }
\ No newline at end of file
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:ffmpeg_kit_flutter_new/ffmpeg_kit.dart';
import 'package:ffmpeg_kit_flutter_new/ffmpeg_session.dart';
import 'package:ffmpeg_kit_flutter_new/ffprobe_kit.dart';
import 'package:ffmpeg_kit_flutter_new/ffprobe_session.dart';
import 'package:ffmpeg_kit_flutter_new/log.dart';
import 'package:ffmpeg_kit_flutter_new/return_code.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import '../modelo/modelo.dart'; import '../modelo/modelo.dart';
...@@ -218,64 +211,25 @@ class _PaginaFotogramaState extends State<PaginaFotograma> { ...@@ -218,64 +211,25 @@ class _PaginaFotogramaState extends State<PaginaFotograma> {
Future<void> loadNumberFotogramas() async { Future<void> loadNumberFotogramas() async {
// Obtener número de fotogramas // Obtener número de fotogramas
FFprobeSession session = await FFprobeKit.execute( int? numFotogramas = await Conversor.getNumFotogramas(widget._archivo);
'-v error -select_streams v:0 -count_frames -show_entries stream=nb_read_frames -of csv=p=0 -i ${widget._archivo.file.path}' if(numFotogramas != null && numFotogramas > 0){
); setState(() {
String? numFoto = await session.getOutput(); _ultimoFotograma = numFotogramas-1;
});
// Obtener duración del vídeo
FFprobeSession session2 = await FFprobeKit.execute(
'-v 0 -of csv="p=0" -select_streams V:0 -show_entries stream=duration -i ${widget._archivo.file.path}'
);
String? durat = await session2.getOutput();
if(durat != null){
double? res = double.tryParse(durat);
if(res != null && res > 0){
setState(() {
_duracionVideo = res-1;
});
}
} }
// Obtener duración de vídeo
if(numFoto != null){ double? duracion = await Conversor.getDuracionVideo(widget._archivo);
int? res = int.tryParse(numFoto); if(duracion != null && duracion > 0){
if(res != null && res > 0){ setState(() {
setState(() { _duracionVideo = duracion-1;
_ultimoFotograma = res-1; });
});
}
} }
} }
Future<File> loadFotograma(int fotograma) async { Future<File> loadFotograma(int fotograma) async {
final directory = await getApplicationSupportDirectory(); final directory = await getApplicationSupportDirectory();
String pathArchivo = widget._archivo.file.path; String pathSalida = '${directory.absolute.path}${Platform.pathSeparator}fotograma.${widget._archivo.formatoDestino?.extension}';
String pathSalida = '${directory.absolute.path}${Platform.pathSeparator}fotograma.png'; await Conversor.getFotograma(widget._archivo, fotograma);
// Cálculo de la timestamp del fotograma a extraer
final double timeStamp = (fotograma/_ultimoFotograma)*_duracionVideo;
String hour, min, sec;
sec = ((timeStamp % 60.0) % 60.0).toString();
while(sec.indexOf('.') < 2){
sec = '0$sec';
}
min = ((timeStamp / 60).floor() % 60).toString();
min = min.padLeft(2,'0');
hour = (timeStamp / 3600).floor().toString();
hour = hour.padLeft(2,'0');
// Este comando extrae un frame del timestamp dado
// La opción -y acepta hacer overwrite
// Si se quiere añadir timestamp se hace con -ss 00:00:00
String commando = '-y -i $pathArchivo -ss $hour:$min:$sec -frames:v 1 $pathSalida';
try{
FFmpegSession session = await FFmpegKit.execute(commando);
} on PlatformException {}
return File(pathSalida).create(); return File(pathSalida).create();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment