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

parent 08ff2f1b
...@@ -7,6 +7,7 @@ import 'formato.dart'; ...@@ -7,6 +7,7 @@ import 'formato.dart';
class Archivo extends Convertible { class Archivo extends Convertible {
final File file; final File file;
late final Future<List<Metadato>> metadatos; late final Future<List<Metadato>> metadatos;
int? fotograma;
Archivo({required super.id, required this.file}): Archivo({required super.id, required this.file}):
super( super(
......
import 'dart:io'; import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
import 'convertible.dart'; import 'convertible.dart';
...@@ -104,4 +105,13 @@ class InfoFormato extends Convertible { ...@@ -104,4 +105,13 @@ class InfoFormato extends Convertible {
icon: const Icon(Icons.find_in_page_outlined), icon: const Icon(Icons.find_in_page_outlined),
formatoOriginal: formato 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{ ...@@ -12,7 +12,6 @@ class Convertible extends ElementoSeleccionable{
required Formato formatoOriginal}): required Formato formatoOriginal}):
_formatoOriginal = formatoOriginal; _formatoOriginal = formatoOriginal;
@override
void convertir(){ void convertir(){
// TODO: <implement> // TODO: <implement>
} }
......
...@@ -28,7 +28,15 @@ class _PaginaAjustesState extends State<PaginaAjustes> { ...@@ -28,7 +28,15 @@ class _PaginaAjustesState extends State<PaginaAjustes> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( 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, backgroundColor: Theme.of(context).primaryColor,
), ),
body: ListView( body: ListView(
......
...@@ -82,7 +82,11 @@ class _PaginaConfiguracionState extends State<PaginaConfiguracion> { ...@@ -82,7 +82,11 @@ class _PaginaConfiguracionState extends State<PaginaConfiguracion> {
if (widget._elementoAsociado is Archivo) { if (widget._elementoAsociado is Archivo) {
var archivo = widget._elementoAsociado as Archivo; var archivo = widget._elementoAsociado as Archivo;
if (esFormatoVideo) { if (esFormatoVideo) {
_paginas.add(PaginaFotograma()); _paginas.add(PaginaFotograma(
lista: widget._lista,
archivo: archivo,
indice: widget._indice,
));
} }
_paginas.add( _paginas.add(
FutureBuilder( FutureBuilder(
...@@ -110,7 +114,7 @@ class _PaginaConfiguracionState extends State<PaginaConfiguracion> { ...@@ -110,7 +114,7 @@ class _PaginaConfiguracionState extends State<PaginaConfiguracion> {
final items = <BottomNavigationBarItem>[ final items = <BottomNavigationBarItem>[
const BottomNavigationBarItem( const BottomNavigationBarItem(
icon: Icon(Icons.sync), icon: Icon(Icons.sync),
label: 'Formato de Conversión' label: 'Formato'
), ),
]; ];
......
import 'dart:async'; 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:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import '../modelo/modelo.dart';
class PaginaFotograma extends StatefulWidget { 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 @override
State<PaginaFotograma> createState() => _PaginaFotogramaState(); State<PaginaFotograma> createState() => _PaginaFotogramaState();
...@@ -10,12 +27,66 @@ class PaginaFotograma extends StatefulWidget { ...@@ -10,12 +27,66 @@ class PaginaFotograma extends StatefulWidget {
class _PaginaFotogramaState extends State<PaginaFotograma> { class _PaginaFotogramaState extends State<PaginaFotograma> {
int _fotogramaSeleccionado = 0; int _fotogramaSeleccionado = 0;
final int _ultimoFotograma = 1200; int _ultimoFotograma = 0;
final _buttons = _IconButtons.values; final _buttons = _IconButtons.values;
Timer? timer; Timer? timer;
@override @override
void initState() {
loadNumberFotogramas();
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) { 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( return Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Column( child: Column(
...@@ -24,7 +95,21 @@ class _PaginaFotogramaState extends State<PaginaFotograma> { ...@@ -24,7 +95,21 @@ class _PaginaFotogramaState extends State<PaginaFotograma> {
children: [ children: [
SizedBox( SizedBox(
height: (MediaQuery.of(context).size.width - 16.0*2)*9.0/16.0, 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), const SizedBox(height: 48.0),
Slider( Slider(
...@@ -45,7 +130,7 @@ class _PaginaFotogramaState extends State<PaginaFotograma> { ...@@ -45,7 +130,7 @@ class _PaginaFotogramaState extends State<PaginaFotograma> {
style: Theme.of(context).textTheme.titleLarge, style: Theme.of(context).textTheme.titleLarge,
), ),
TextSpan( TextSpan(
text: _fotogramaSeleccionado.toString(), text: (_fotogramaSeleccionado+1).toString(),
style: Theme.of(context).textTheme.titleLarge?.copyWith( style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold fontWeight: FontWeight.bold
), ),
...@@ -55,8 +140,8 @@ class _PaginaFotogramaState extends State<PaginaFotograma> { ...@@ -55,8 +140,8 @@ class _PaginaFotogramaState extends State<PaginaFotograma> {
), ),
const SizedBox(height: 24.0), const SizedBox(height: 24.0),
_construirBotonesFotograma(context) _construirBotonesFotograma(context)
], ]
), )
); );
} }
...@@ -107,6 +192,43 @@ class _PaginaFotogramaState extends State<PaginaFotograma> { ...@@ -107,6 +192,43 @@ class _PaginaFotogramaState extends State<PaginaFotograma> {
children: buttons, 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{ enum _IconButtons{
......
...@@ -81,14 +81,22 @@ packages: ...@@ -81,14 +81,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.3" 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" dependency: "direct main"
description: description:
name: ffmpeg_kit_flutter name: ffmpeg_kit_flutter_new
sha256: "843aae41823ca94a0988d975b4b6cdc6948744b9b7e2707d81a3a9cd237b0100" sha256: dbaf0f4963b08a034a4f787276c1e12efc36a56670693f1721e46f95554f0979
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.3" version: "1.6.1"
ffmpeg_kit_flutter_platform_interface: ffmpeg_kit_flutter_platform_interface:
dependency: transitive dependency: transitive
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