Página de fotogramas ya funciona

parent 85efb35b
Showing with 91 additions and 23 deletions
...@@ -4,8 +4,10 @@ import 'package:ffmpeg_kit_flutter_new/ffmpeg_kit.dart'; ...@@ -4,8 +4,10 @@ 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/ffprobe_kit.dart';
import 'package:ffmpeg_kit_flutter_new/ffprobe_session.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: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';
...@@ -29,18 +31,23 @@ class PaginaFotograma extends StatefulWidget { ...@@ -29,18 +31,23 @@ class PaginaFotograma extends StatefulWidget {
class _PaginaFotogramaState extends State<PaginaFotograma> { class _PaginaFotogramaState extends State<PaginaFotograma> {
int _fotogramaSeleccionado = 0; int _fotogramaSeleccionado = 0;
int _ultimoFotograma = 0; int _ultimoFotograma = 0;
double _duracionVideo = 0;
final _buttons = _IconButtons.values; final _buttons = _IconButtons.values;
Timer? timer; Timer? timer;
@override @override
void initState() { void initState() {
loadNumberFotogramas(); loadNumberFotogramas();
if(widget._archivo.fotograma != null){
_fotogramaSeleccionado = widget._archivo.fotograma!;
}
super.initState(); super.initState();
} }
@override @override
void dispose() { void dispose() {
clearTemp();
super.dispose(); super.dispose();
} }
...@@ -100,7 +107,11 @@ class _PaginaFotogramaState extends State<PaginaFotograma> { ...@@ -100,7 +107,11 @@ class _PaginaFotogramaState extends State<PaginaFotograma> {
future: loadFotograma(_fotogramaSeleccionado), future: loadFotograma(_fotogramaSeleccionado),
builder: (context, asyncSnapshot) { builder: (context, asyncSnapshot) {
if(asyncSnapshot.connectionState == ConnectionState.done){ if(asyncSnapshot.connectionState == ConnectionState.done){
return Image.file(asyncSnapshot.data!); imageCache.clear();
return Image.file(
asyncSnapshot.data!,
key: UniqueKey(),
);
} }
else{ else{
return Transform.scale( return Transform.scale(
...@@ -118,9 +129,14 @@ class _PaginaFotogramaState extends State<PaginaFotograma> { ...@@ -118,9 +129,14 @@ class _PaginaFotogramaState extends State<PaginaFotograma> {
max: _ultimoFotograma.toDouble(), max: _ultimoFotograma.toDouble(),
divisions: _ultimoFotograma, divisions: _ultimoFotograma,
value: _fotogramaSeleccionado.toDouble(), value: _fotogramaSeleccionado.toDouble(),
label: _fotogramaSeleccionado.toString(), label: (_fotogramaSeleccionado+1).toString(),
onChanged: (value) { onChanged: (value) {
setState(() { _fotogramaSeleccionado = value.toInt(); }); setState(() {
_fotogramaSeleccionado = value.toInt();
});
widget._archivo.fotograma = _fotogramaSeleccionado;
widget._lista.actualizaSeleccionable(widget._indice, widget._archivo);
} }
), ),
RichText( RichText(
...@@ -158,6 +174,9 @@ class _PaginaFotogramaState extends State<PaginaFotograma> { ...@@ -158,6 +174,9 @@ class _PaginaFotogramaState extends State<PaginaFotograma> {
if(_fotogramaSeleccionado < 0) _fotogramaSeleccionado = 0; if(_fotogramaSeleccionado < 0) _fotogramaSeleccionado = 0;
if(_fotogramaSeleccionado > _ultimoFotograma) _fotogramaSeleccionado = _ultimoFotograma; if(_fotogramaSeleccionado > _ultimoFotograma) _fotogramaSeleccionado = _ultimoFotograma;
}); });
widget._archivo.fotograma = _fotogramaSeleccionado;
widget._lista.actualizaSeleccionable(widget._indice, widget._archivo);
}); });
}); });
}, },
...@@ -179,6 +198,9 @@ class _PaginaFotogramaState extends State<PaginaFotograma> { ...@@ -179,6 +198,9 @@ class _PaginaFotogramaState extends State<PaginaFotograma> {
_fotogramaSeleccionado += button.variation; _fotogramaSeleccionado += button.variation;
if(_fotogramaSeleccionado < 0) _fotogramaSeleccionado = 0; if(_fotogramaSeleccionado < 0) _fotogramaSeleccionado = 0;
if(_fotogramaSeleccionado > _ultimoFotograma) _fotogramaSeleccionado = _ultimoFotograma; if(_fotogramaSeleccionado > _ultimoFotograma) _fotogramaSeleccionado = _ultimoFotograma;
widget._archivo.fotograma = _fotogramaSeleccionado;
widget._lista.actualizaSeleccionable(widget._indice, widget._archivo);
}); });
}, },
), ),
...@@ -195,43 +217,73 @@ class _PaginaFotogramaState extends State<PaginaFotograma> { ...@@ -195,43 +217,73 @@ class _PaginaFotogramaState extends State<PaginaFotograma> {
} }
Future<void> loadNumberFotogramas() async { Future<void> loadNumberFotogramas() async {
FFprobeSession session = await FFprobeKit.executeAsync( // Obtener número de fotogramas
'ffprobe -v error -select_streams v:0 -count_packets \\ -show_entries stream=nb_read_packets -of csv=p=0 ${widget._archivo.file.absolute.path}' FFprobeSession session = await FFprobeKit.execute(
'-v error -select_streams v:0 -count_frames -show_entries stream=nb_read_frames -of csv=p=0 -i ${widget._archivo.file.path}'
);
String? numFoto = await session.getOutput();
// 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? output = await session.getAllLogsAsString(); String? durat = await session2.getOutput();
print(output);
if(durat != null){
double? res = double.tryParse(durat);
if(res != null && res > 0){
setState(() {
_duracionVideo = res-1;
});
}
}
if(output != null){ if(numFoto != null){
int? res = int.tryParse(output); int? res = int.tryParse(numFoto);
if(res != null && res > 0){ if(res != null && res > 0){
setState(() { setState(() {
_ultimoFotograma = res; _ultimoFotograma = res-1;
}); });
} }
} }
setState(() {
_ultimoFotograma = 1200;
});
} }
Future<File> loadFotograma(int fotograma) async { Future<File> loadFotograma(int fotograma) async {
final directory = await getApplicationSupportDirectory(); final directory = await getApplicationSupportDirectory();
// Este comando extrae un frame del timestamp dado. Por ahora solo extrae el primer frame String pathArchivo = widget._archivo.file.path;
// TODO: CONVERTIR FOTOGRAMA A TIMESTAMP
String pathArchivo = widget._archivo.file.absolute.path;
String pathSalida = '${directory.absolute.path}${Platform.pathSeparator}fotograma.png'; String pathSalida = '${directory.absolute.path}${Platform.pathSeparator}fotograma.png';
// 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 // La opción -y acepta hacer overwrite
// Si se quiere añadir timestamp se hace con -ss 00:00:00 // Si se quiere añadir timestamp se hace con -ss 00:00:00
String commando = '-y -i $pathArchivo -frames:v 1 $pathSalida'; String commando = '-y -i $pathArchivo -ss $hour:$min:$sec -frames:v 1 $pathSalida';
FFmpegSession session = await FFmpegKit.executeAsync(commando); try{
FFmpegSession session = await FFmpegKit.execute(commando);
} on PlatformException {}
return File(pathSalida).create(); return File(pathSalida).create();
} }
Future<void> removeFotograma() async { Future<void> clearTemp() async {
final directory = await getApplicationSupportDirectory(); final directory = await getApplicationSupportDirectory();
final fotograma = File('${directory.absolute.path}${Platform.pathSeparator}fotograma.png'); final list = directory.listSync();
if(await fotograma.exists()){ for(var arch in list){
await fotograma.delete(); await arch.delete();
} }
} }
} }
......
# Generated by pub # Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile # See https://dart.dev/tools/pub/glossary#lockfile
packages: packages:
archive:
dependency: "direct main"
description:
name: archive
sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd"
url: "https://pub.dev"
source: hosted
version: "4.0.7"
async: async:
dependency: transitive dependency: transitive
description: description:
...@@ -408,6 +416,14 @@ packages: ...@@ -408,6 +416,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.8" version: "2.1.8"
posix:
dependency: transitive
description:
name: posix
sha256: f0d7856b6ca1887cfa6d1d394056a296ae33489db914e365e2044fdada449e62
url: "https://pub.dev"
source: hosted
version: "6.0.2"
provider: provider:
dependency: "direct main" dependency: "direct main"
description: description:
......
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