Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Rafa Castillo Passols
/
Prototipo-Multimedia
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
0a923a47
authored
May 26, 2025
by
Diego Pérez Peña
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Página de fotogramas ya funciona
parent
85efb35b
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
91 additions
and
23 deletions
lib/paginas/pagina_fotograma.dart
pubspec.lock
lib/paginas/pagina_fotograma.dart
View file @
0a923a47
...
...
@@ -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/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/services.dart'
;
import
'package:path_provider/path_provider.dart'
;
import
'../modelo/modelo.dart'
;
...
...
@@ -29,18 +31,23 @@ class PaginaFotograma extends StatefulWidget {
class
_PaginaFotogramaState
extends
State
<
PaginaFotograma
>
{
int
_fotogramaSeleccionado
=
0
;
int
_ultimoFotograma
=
0
;
double
_duracionVideo
=
0
;
final
_buttons
=
_IconButtons
.
values
;
Timer
?
timer
;
@override
void
initState
()
{
loadNumberFotogramas
();
if
(
widget
.
_archivo
.
fotograma
!=
null
){
_fotogramaSeleccionado
=
widget
.
_archivo
.
fotograma
!;
}
super
.
initState
();
}
@override
void
dispose
()
{
clearTemp
();
super
.
dispose
();
}
...
...
@@ -100,7 +107,11 @@ class _PaginaFotogramaState extends State<PaginaFotograma> {
future:
loadFotograma
(
_fotogramaSeleccionado
),
builder:
(
context
,
asyncSnapshot
)
{
if
(
asyncSnapshot
.
connectionState
==
ConnectionState
.
done
){
return
Image
.
file
(
asyncSnapshot
.
data
!);
imageCache
.
clear
();
return
Image
.
file
(
asyncSnapshot
.
data
!,
key:
UniqueKey
(),
);
}
else
{
return
Transform
.
scale
(
...
...
@@ -118,9 +129,14 @@ class _PaginaFotogramaState extends State<PaginaFotograma> {
max:
_ultimoFotograma
.
toDouble
(),
divisions:
_ultimoFotograma
,
value:
_fotogramaSeleccionado
.
toDouble
(),
label:
_fotogramaSeleccionado
.
toString
(),
label:
(
_fotogramaSeleccionado
+
1
)
.
toString
(),
onChanged:
(
value
)
{
setState
(()
{
_fotogramaSeleccionado
=
value
.
toInt
();
});
setState
(()
{
_fotogramaSeleccionado
=
value
.
toInt
();
});
widget
.
_archivo
.
fotograma
=
_fotogramaSeleccionado
;
widget
.
_lista
.
actualizaSeleccionable
(
widget
.
_indice
,
widget
.
_archivo
);
}
),
RichText
(
...
...
@@ -158,6 +174,9 @@ class _PaginaFotogramaState extends State<PaginaFotograma> {
if
(
_fotogramaSeleccionado
<
0
)
_fotogramaSeleccionado
=
0
;
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> {
_fotogramaSeleccionado
+=
button
.
variation
;
if
(
_fotogramaSeleccionado
<
0
)
_fotogramaSeleccionado
=
0
;
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> {
}
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}
'
// Obtener número de fotogramas
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
();
print
(
output
);
String
?
durat
=
await
session2
.
getOutput
();
if
(
durat
!=
null
){
double
?
res
=
double
.
tryParse
(
durat
);
if
(
res
!=
null
&&
res
>
0
){
setState
(()
{
_duracionVideo
=
res
-
1
;
});
}
}
if
(
output
!=
null
){
int
?
res
=
int
.
tryParse
(
output
);
if
(
numFoto
!=
null
){
int
?
res
=
int
.
tryParse
(
numFoto
);
if
(
res
!=
null
&&
res
>
0
){
setState
(()
{
_ultimoFotograma
=
res
;
_ultimoFotograma
=
res
-
1
;
});
}
}
setState
(()
{
_ultimoFotograma
=
1200
;
});
}
Future
<
File
>
loadFotograma
(
int
fotograma
)
async
{
final
directory
=
await
getApplicationSupportDirectory
();
// Este comando extrae un frame del timestamp dado. Por ahora solo extrae el primer frame
// TODO: CONVERTIR FOTOGRAMA A TIMESTAMP
String
pathArchivo
=
widget
.
_archivo
.
file
.
absolute
.
path
;
String
pathArchivo
=
widget
.
_archivo
.
file
.
path
;
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
// Si se quiere añadir timestamp se hace con -ss 00:00:00
String
commando
=
'-y -i
$pathArchivo
-frames:v 1
$pathSalida
'
;
FFmpegSession
session
=
await
FFmpegKit
.
executeAsync
(
commando
);
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
();
}
Future
<
void
>
removeFotograma
()
async
{
Future
<
void
>
clearTemp
()
async
{
final
directory
=
await
getApplicationSupportDirectory
();
final
fotograma
=
File
(
'
${directory.absolute.path}${Platform.pathSeparator}
fotograma.png'
);
if
(
await
fotograma
.
exists
()
){
await
fotograma
.
delete
();
final
list
=
directory
.
listSync
(
);
for
(
var
arch
in
list
){
await
arch
.
delete
();
}
}
}
...
...
pubspec.lock
View file @
0a923a47
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
archive:
dependency: "direct main"
description:
name: archive
sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd"
url: "https://pub.dev"
source: hosted
version: "4.0.7"
async:
dependency: transitive
description:
...
...
@@ -408,6 +416,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.8"
posix:
dependency: transitive
description:
name: posix
sha256: f0d7856b6ca1887cfa6d1d394056a296ae33489db914e365e2044fdada449e62
url: "https://pub.dev"
source: hosted
version: "6.0.2"
provider:
dependency: "direct main"
description:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment