Página de fotogramas supuestamente funcional, bug de carpeta arreglado

parent 08ff2f1b
......@@ -7,6 +7,7 @@ import 'formato.dart';
class Archivo extends Convertible {
final File file;
late final Future<List<Metadato>> metadatos;
int? fotograma;
Archivo({required super.id, required this.file}):
super(
......
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:uuid/uuid.dart';
import 'convertible.dart';
......@@ -104,4 +105,13 @@ class InfoFormato extends Convertible {
icon: const Icon(Icons.find_in_page_outlined),
formatoOriginal: formato
);
bool operator ==(Object other) =>
other is InfoFormato &&
other.runtimeType == runtimeType &&
other.formatoOriginal == formatoOriginal;
@override
int get hashCode => Object.hash(formatoOriginal, formatoDestino, calidadSalida, _carpeta, seleccionado, subCarpeta);
}
\ No newline at end of file
......@@ -12,7 +12,6 @@ class Convertible extends ElementoSeleccionable{
required Formato formatoOriginal}):
_formatoOriginal = formatoOriginal;
@override
void convertir(){
// TODO: <implement>
}
......
......@@ -28,7 +28,15 @@ class _PaginaAjustesState extends State<PaginaAjustes> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Ajustes"),
leading: BackButton(
color: Colors.white,
),
title: Text(
"Ajustes",
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: Colors.white
),
),
backgroundColor: Theme.of(context).primaryColor,
),
body: ListView(
......
......@@ -82,7 +82,11 @@ class _PaginaConfiguracionState extends State<PaginaConfiguracion> {
if (widget._elementoAsociado is Archivo) {
var archivo = widget._elementoAsociado as Archivo;
if (esFormatoVideo) {
_paginas.add(PaginaFotograma());
_paginas.add(PaginaFotograma(
lista: widget._lista,
archivo: archivo,
indice: widget._indice,
));
}
_paginas.add(
FutureBuilder(
......@@ -110,7 +114,7 @@ class _PaginaConfiguracionState extends State<PaginaConfiguracion> {
final items = <BottomNavigationBarItem>[
const BottomNavigationBarItem(
icon: Icon(Icons.sync),
label: 'Formato de Conversión'
label: 'Formato'
),
];
......
import 'dart:async';
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:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import '../modelo/modelo.dart';
class PaginaFotograma extends StatefulWidget {
const PaginaFotograma({super.key});
final ListaSeleccionables _lista;
final Archivo _archivo;
final int _indice;
const PaginaFotograma({
super.key,
required ListaSeleccionables lista,
required Archivo archivo,
required int indice,
}): _lista = lista, _archivo = archivo, _indice = indice;
@override
State<PaginaFotograma> createState() => _PaginaFotogramaState();
......@@ -10,12 +27,66 @@ class PaginaFotograma extends StatefulWidget {
class _PaginaFotogramaState extends State<PaginaFotograma> {
int _fotogramaSeleccionado = 0;
final int _ultimoFotograma = 1200;
int _ultimoFotograma = 0;
final _buttons = _IconButtons.values;
Timer? timer;
@override
void initState() {
loadNumberFotogramas();
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
if(widget._archivo.formatoDestino == null){
return Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Para seleccionar un fotograma debe elegir un formato de imagen',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge,
),
),
);
}
if(widget._archivo.formatoDestino!.tipoMultimedia != TipoMultimedia.imagen){
return Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'El formato seleccionado no es un formato de imagen',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge,
),
),
);
}
if(_ultimoFotograma == 0){
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
Text(
'Cargando...',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge,
)
],
),
);
}
return Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
......@@ -24,7 +95,21 @@ class _PaginaFotogramaState extends State<PaginaFotograma> {
children: [
SizedBox(
height: (MediaQuery.of(context).size.width - 16.0*2)*9.0/16.0,
child: Placeholder(),
child: FutureBuilder(
future: loadFotograma(_fotogramaSeleccionado),
builder: (context, asyncSnapshot) {
if(asyncSnapshot.connectionState == ConnectionState.done){
return Image.file(asyncSnapshot.data!);
}
else{
return Transform.scale(
scaleX: 2,
scaleY: 2/5,
child: CircularProgressIndicator()
);
}
}
),
),
const SizedBox(height: 48.0),
Slider(
......@@ -45,7 +130,7 @@ class _PaginaFotogramaState extends State<PaginaFotograma> {
style: Theme.of(context).textTheme.titleLarge,
),
TextSpan(
text: _fotogramaSeleccionado.toString(),
text: (_fotogramaSeleccionado+1).toString(),
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold
),
......@@ -55,8 +140,8 @@ class _PaginaFotogramaState extends State<PaginaFotograma> {
),
const SizedBox(height: 24.0),
_construirBotonesFotograma(context)
],
),
]
)
);
}
......@@ -107,6 +192,43 @@ class _PaginaFotogramaState extends State<PaginaFotograma> {
children: buttons,
);
}
Future<void> loadNumberFotogramas() async {
FFprobeSession session = await FFprobeKit.executeAsync(
'ffprobe -v error -select_streams v:0 -count_packets \\ -show_entries stream=nb_read_packets -of csv=p=0 ${widget._archivo.file.absolute.path}'
);
String? output = await session.getAllLogsAsString();
print(output);
if(output != null){
int? res = int.tryParse(output);
if(res != null && res > 0){
setState(() {
_ultimoFotograma = res;
});
}
}
setState(() {
_ultimoFotograma = 1200;
});
}
Future<File> loadFotograma(int fotograma) async {
final directory = await getApplicationSupportDirectory();
FFmpegSession session = await FFmpegKit.executeAsync(
'ffmpeg -i ${widget._archivo.file.absolute.path} -vf "select=eq(n\,$fotograma)" -vframes 1 ${directory.absolute.path}${Platform.pathSeparator}fotograma.png'
);
return File('${directory.absolute.path}${Platform.pathSeparator}fotograma.png');
}
Future<void> removeFotograma() async {
final directory = await getApplicationSupportDirectory();
final fotograma = File('${directory.absolute.path}${Platform.pathSeparator}fotograma.png');
if(await fotograma.exists()){
await fotograma.delete();
}
}
}
enum _IconButtons{
......
......@@ -81,14 +81,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.3"
ffmpeg_kit_flutter:
ffmpeg_kit_flutter_android:
dependency: transitive
description:
name: ffmpeg_kit_flutter_android
sha256: "1bcd2e18169862d9782f019e3e83f92a41a12692deb25e0e767ecd44518c0f7e"
url: "https://pub.dev"
source: hosted
version: "1.4.0"
ffmpeg_kit_flutter_new:
dependency: "direct main"
description:
name: ffmpeg_kit_flutter
sha256: "843aae41823ca94a0988d975b4b6cdc6948744b9b7e2707d81a3a9cd237b0100"
name: ffmpeg_kit_flutter_new
sha256: dbaf0f4963b08a034a4f787276c1e12efc36a56670693f1721e46f95554f0979
url: "https://pub.dev"
source: hosted
version: "6.0.3"
version: "1.6.1"
ffmpeg_kit_flutter_platform_interface:
dependency: transitive
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