Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extract from video now directly returns a krec #16

Merged
merged 4 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ eyre = "0.6"
color-eyre = "0.6"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
tempfile = "3.8"

[build-dependencies]

Expand All @@ -28,5 +29,5 @@ resolver = "2"

[workspace.package]

version = "0.2.9"
version = "0.3.0"
edition = "2021"
42 changes: 42 additions & 0 deletions examples/test_extract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import krec
import argparse
from pathlib import Path


"""
# Just extract and view
python examples/test_extract.py input.mkv -v

# Extract and save
python examples/test_extract.py input.mkv -o output.krec -v
"""


def main(args):
print(f"Extracting from: {args.input_file}")

try:
extracted_krec = krec.extract_from_video(args.input_file, verbose=args.verbose)
print("Extraction successful")
print(f"Extracted KRec has {len(extracted_krec)} frames")

if args.output_file:
output_path = Path(args.output_file)
extracted_krec.save(str(output_path))
print(f"Saved to: {output_path}")

except Exception as e:
print(f"Error: {e}")
return 1

return 0


if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Extract KRec data from MKV file")
parser.add_argument("input_file", type=str, help="Input MKV file path")
parser.add_argument("-o", "--output-file", type=str, help="Output KRec file path (optional)")
parser.add_argument("-v", "--verbose", action="store_true", help="Enable verbose output")

args = parser.parse_args()
exit(main(args))
19 changes: 4 additions & 15 deletions krec/bindings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1351,24 +1351,13 @@ fn combine_with_video(video_path: &str, krec_path: &str, output_path: &str) -> P

#[gen_stub_pyfunction]
#[pyfunction]
#[pyo3(signature = (video_path, output_path, verbose=None))]
fn extract_from_video(video_path: &str, output_path: &str, verbose: Option<bool>) -> PyResult<()> {
fn extract_from_video(py: Python<'_>, video_path: &str, verbose: Option<bool>) -> PyResult<PyKRec> {
info!("Python binding: extract_from_video called");
debug!(
"Python binding: video_path={}, output_path={}, verbose={:?}",
video_path, output_path, verbose
);

let result = ::krec::extract_from_video(video_path, output_path, verbose).map_err(|e| {
warn!("Python binding: extract_from_video failed: {}", e);
PyErr::new::<pyo3::exceptions::PyIOError, _>(e.to_string())
});
let krec = ::krec::extract_from_video(video_path, verbose)
.map_err(|e| PyErr::new::<pyo3::exceptions::PyIOError, _>(e.to_string()))?;

if result.is_ok() {
info!("Python binding: extract_from_video completed successfully");
}

result
Ok(PyKRec { inner: krec })
}

#[pymodule]
Expand Down
42 changes: 28 additions & 14 deletions src/ffmpeg.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
use crate::KRec;
use color_eyre::{eyre::eyre, Result};
use std::path::Path;
use tempfile::NamedTempFile;
use thiserror::Error;
use tracing::{debug, info, instrument, warn};

#[derive(Error, Debug)]
pub enum FFmpegError {
#[error("FFmpeg error: {0}")]
FFmpeg(String),
#[error("Input file not found: {0}")]
InputNotFound(String),
}

#[instrument(skip(video_path, krec_path, output_path))]
Expand Down Expand Up @@ -81,20 +84,25 @@ pub fn combine_with_video(
}
}

pub fn extract_from_video(
video_path: &str,
output_path: &str,
verbose: Option<bool>,
) -> Result<(), FFmpegError> {
pub fn extract_from_video(video_path: &str, verbose: Option<bool>) -> Result<KRec, FFmpegError> {
info!("Starting extract_from_video");
debug!("Input video path: {}", video_path);
debug!("Output path: {}", output_path);
debug!("Verbose mode: {}", verbose.unwrap_or(false));

// Check if input file exists
if !Path::new(video_path).exists() {
return Err(FFmpegError::InputNotFound(video_path.to_string()));
}

// Create a temporary file for FFmpeg output
let temp_file = NamedTempFile::new()
.map_err(|e| FFmpegError::FFmpeg(format!("Failed to create temporary file: {}", e)))?;
let temp_path = temp_file.path().to_string_lossy().to_string();

// Construct ffmpeg command
let mut command = std::process::Command::new("ffmpeg");
command.args([
"-y",
"-dump_attachment:t:0",
output_path,
&temp_path,
"-i",
video_path,
"-f",
Expand All @@ -116,12 +124,18 @@ pub fn extract_from_video(
FFmpegError::FFmpeg(e.to_string())
})?;

if status.success() {
info!("Successfully extracted KRec from video");
Ok(())
} else {
if !status.success() {
let error_msg = format!("FFmpeg command failed with status: {}", status);
warn!("{}", error_msg);
Err(FFmpegError::FFmpeg(error_msg))
return Err(FFmpegError::FFmpeg(error_msg));
}

// Load the KRec from the temporary file
let krec = KRec::load(&temp_path).map_err(|e| {
FFmpegError::FFmpeg(format!("Failed to load KRec from temporary file: {}", e))
})?;

// The temporary file will be automatically deleted when temp_file goes out of scope
info!("Successfully extracted KRec from video");
Ok(krec)
}
Loading