Source code for camtasia.export.report
from __future__ import annotations
import json
from pathlib import Path
from typing import TYPE_CHECKING
from camtasia.types import ReportFormat
if TYPE_CHECKING:
from camtasia.project import Project
[docs]
def export_project_report(
project: Project,
output_path: str | Path,
*,
format: ReportFormat = 'markdown',
) -> Path:
"""Export a detailed project report."""
path = Path(output_path)
if format == 'json':
json_report = _build_json_report(project)
path.write_text(json.dumps(json_report, indent=2))
else:
md_report = _build_markdown_report(project)
path.write_text(md_report)
return path
def _build_json_report(project: Project) -> dict:
tracks = []
for track in project.timeline.tracks:
clips = []
for clip in track.clips:
clips.append({
'id': clip.id,
'type': clip.clip_type,
'start_seconds': clip.start_seconds,
'duration_seconds': clip.duration_seconds,
})
tracks.append({
'index': track.index,
'name': track.name,
'clip_count': len(track),
'clips': clips,
})
media = []
for m in project.media_bin:
media.append({
'id': m.id,
'identity': m.identity,
'type': m.type.name if m.type is not None and hasattr(m.type, 'name') else str(m.type),
})
return {
'project': str(project.file_path.name),
'canvas': {'width': project.width, 'height': project.height},
'duration_seconds': project.total_duration_seconds(),
'track_count': project.timeline.track_count,
'tracks': tracks,
'media_count': len(project.media_bin),
'media': media,
}
def _build_markdown_report(project: Project) -> str:
lines = [
f'# Project Report: {project.file_path.name}',
'',
f'**Canvas:** {project.width}×{project.height}',
f'**Duration:** {project.total_duration_seconds():.1f}s',
f'**Tracks:** {project.timeline.track_count}',
f'**Media:** {len(project.media_bin)} items',
'',
'## Tracks',
'',
]
for track in project.timeline.tracks:
clip_count = len(track)
if clip_count > 0:
types = sorted({c.clip_type for c in track.clips})
lines.append(f'### Track {track.index}: {track.name or "(unnamed)"}')
lines.append(f'- {clip_count} clips: {", ".join(types)}')
lines.append('')
lines.append('## Media Bin')
lines.append('')
for m in project.media_bin:
type_name = m.type.name if m.type is not None and hasattr(m.type, 'name') else str(m.type)
lines.append(f'- [{m.id}] {m.identity} ({type_name})')
lines.append('')
return '\n'.join(lines)