Skip to content

Commit

Permalink
Merge pull request #101 from TheAcharya/timeline-detection
Browse files Browse the repository at this point in the history
Timeline Detection
  • Loading branch information
orchetect authored May 20, 2024
2 parents 7a95183 + bccab95 commit f7007e3
Show file tree
Hide file tree
Showing 35 changed files with 265 additions and 196 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@

## 0.3.7

### New Features

- Extraction now supports FCPXML containing a standalone clip without a project (#99)

### Bug Fixes

- Output folder name timestamp now formats as 24-hour time (#100)

### Changes

- Renamed `projectTimecode` naming mode to `timelineNameAndTimecode` (#99)

## [0.3.6](https://github.com/TheAcharya/MarkersExtractor/releases/tag/0.3.6) (2024-05-05)

### New Features
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ let package = Package(
.package(url: "https://github.com/apple/swift-collections.git", from: "1.1.0"),
.package(url: "https://github.com/orchetect/TextFileKit.git", from: "0.1.6"),
.package(url: "https://github.com/orchetect/TimecodeKit.git", from: "2.0.10"),
.package(url: "https://github.com/orchetect/DAWFileKit.git", from: "0.4.8"),
.package(url: "https://github.com/orchetect/DAWFileKit.git", branch: "main"),
.package(url: "https://github.com/orchetect/OTCore.git", from: "1.5.3"),
],
targets: [
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,9 @@ OPTIONS:
for GIF: 50)
--gif-fps <0.1...60.0> GIF frame rate. (default: 10.0)
--gif-span <sec> GIF capture span around marker. (default: 2.0)
--id-naming-mode <projectTimecode | name | notes>
--id-naming-mode <timelineNameAndTimecode | name | notes>
Marker naming mode. This affects Marker IDs and image
filenames. (default: projectTimecode)
filenames. (default: timelineNameAndTimecode)
--label <id | name | type | checked | status | notes | reel | scene | take | position | clipType | clipName | clipIn | clipOut | clipDuration | clipKeywords | videoRole | audioRole | eventName | projectName | libraryName | iconImage | imageFileName>
Label to overlay on thumb images. This argument can
be supplied more than once to apply multiple labels.
Expand Down Expand Up @@ -352,7 +352,8 @@ It is recommended to read this file with a JSON parser to obtain the values for

### Intended Behaviour & Logic

The tool will only parse markers of your project's main timeline.
The tool operates on a single Final Cut Pro timeline. If the FCPXML data contains a project, the project's main timeline will be used. If a standalone clip is present instead of a project, the clip's timeline will be used.

Markers nested deep within compound, multicam or synchronized clips will be ignored.

### Developer Library
Expand Down
8 changes: 4 additions & 4 deletions Sources/MarkersExtractor/Export/ExportFolderFormat.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ public enum ExportFolderFormat: String, CaseIterable, Equatable, Hashable {
}

extension ExportFolderFormat {
func folderName(projectName: String, profile: ExportProfileFormat) -> String {
func folderName(timelineName: String, profile: ExportProfileFormat) -> String {
switch self {
case .short:
return "\(projectName)"
return "\(timelineName)"
case .medium:
return "\(projectName) \(nowTimestamp(twentyFourHour: true))"
return "\(timelineName) \(nowTimestamp(twentyFourHour: true))"
case .long:
return "\(projectName) \(nowTimestamp(twentyFourHour: true)) [\(profile.name)]"
return "\(timelineName) \(nowTimestamp(twentyFourHour: true)) [\(profile.name)]"
}
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/MarkersExtractor/Export/ExportMedia.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ extension ExportProfile {
let offsets: [Timecode] = zip(markers, preparedMarkers)
.map { marker, preparedMarker in
if isVideoPresent {
let projectStart = marker.parentInfo.projectStartTime
let offset = preparedMarker.imageTimecode - projectStart
let timelineStart = marker.parentInfo.timelineStartTime
let offset = preparedMarker.imageTimecode - timelineStart
return offset
} else {
return Timecode(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import Foundation
public struct CSVExportPayload: ExportPayload {
let csvPath: URL

init(projectName: String, outputURL: URL) {
let csvName = "\(projectName).csv"
init(timelineName: String, outputURL: URL) {
let csvName = "\(timelineName).csv"
csvPath = outputURL.appendingPathComponent(csvName)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ public struct CSVJSONExportPayload: ExportPayload {
let csvPayload: CSVExportPayload
let jsonPayload: JSONExportPayload

init(projectName: String, outputURL: URL) {
csvPayload = .init(projectName: projectName, outputURL: outputURL)
jsonPayload = .init(projectName: projectName, outputURL: outputURL)
init(timelineName: String, outputURL: URL) {
csvPayload = .init(timelineName: timelineName, outputURL: outputURL)
jsonPayload = .init(timelineName: timelineName, outputURL: outputURL)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import Foundation
public struct JSONExportPayload: ExportPayload {
let jsonPath: URL

init(projectName: String, outputURL: URL) {
let jsonName = "\(projectName).json"
init(timelineName: String, outputURL: URL) {
let jsonName = "\(timelineName).json"
jsonPath = outputURL.appendingPathComponent(jsonName)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ import TimecodeKit

public struct MIDIFileExportPayload: ExportPayload {
let midiFilePath: URL
let sessionStartTimecode: Timecode
let timelineStartTimecode: Timecode

init(
projectName: String,
timelineName: String,
outputURL: URL,
sessionStartTimecode: Timecode
timelineStartTimecode: Timecode
) {
let midiFileName = "\(projectName).mid"
let midiFileName = "\(timelineName).mid"
midiFilePath = outputURL.appendingPathComponent(midiFileName)

self.sessionStartTimecode = sessionStartTimecode
self.timelineStartTimecode = timelineStartTimecode
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import Foundation
public struct TSVExportPayload: ExportPayload {
let tsvPath: URL

init(projectName: String, outputURL: URL) {
let tsvName = "\(projectName).tsv"
init(timelineName: String, outputURL: URL) {
let tsvName = "\(timelineName).tsv"
tsvPath = outputURL.appendingPathComponent(tsvName)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import Foundation
public struct TextExportPayload: ExportPayload {
let txtPath: URL

init(projectName: String, outputURL: URL) {
let txtName = "\(projectName).txt"
init(timelineName: String, outputURL: URL) {
let txtName = "\(timelineName).txt"
txtPath = outputURL.appendingPathComponent(txtName)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ extension MIDIFileExportProfile {
let midiFile = try MIDIFile(
converting: dawMarkers,
tempo: 120.0,
startTimecode: payload.sessionStartTimecode,
startTimecode: payload.timelineStartTimecode,
includeComments: false,
buildMessages: &buildMessages
)
Expand Down Expand Up @@ -110,7 +110,7 @@ public struct MIDIFileExportMarker: ExportMarker {
frameRate = marker.frameRate()
subFramesBase = marker.subFramesBase()
imageFileName = UUID().uuidString // never used, just dummy
imageTimecode = marker.imageTimecode(useChapterMarkerPosterOffset: false, offsetToProjectStart: false) // not used
imageTimecode = marker.imageTimecode(useChapterMarkerPosterOffset: false, offsetToTimelineStart: false) // not used
}

/// Convert to a DAWFileKit `DAWMarker`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ extension YouTubeProfile {
mediaInfo: mediaInfo,
tcStringFormat: tcStringFormat,
timeFormat: .realTime(stringFormat: .shortest),
offsetToProjectStart: true,
offsetToTimelineStart: true,
useChapterMarkerPosterOffset: useChapterMarkerPosterOffset
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public struct StandardExportMarker: ExportMarker {
mediaInfo: ExportMarkerMediaInfo?,
tcStringFormat: Timecode.StringFormat,
timeFormat: ExportMarkerTimeFormat,
offsetToProjectStart: Bool = false,
offsetToTimelineStart: Bool = false,
useChapterMarkerPosterOffset: Bool
) {
id = marker.id(idMode, tcStringFormat: tcStringFormat)
Expand All @@ -59,7 +59,7 @@ public struct StandardExportMarker: ExportMarker {
reel = marker.metadata.reel
scene = marker.metadata.scene
take = marker.metadata.take
position = marker.positionTimeString(format: timeFormat, offsetToProjectStart: offsetToProjectStart)
position = marker.positionTimeString(format: timeFormat, offsetToTimelineStart: offsetToTimelineStart)
clipType = marker.parentInfo.clipType
clipName = marker.parentInfo.clipName
clipIn = marker.parentInfo.clipInTimeString(format: timeFormat)
Expand All @@ -68,9 +68,9 @@ public struct StandardExportMarker: ExportMarker {
clipKeywords = marker.parentInfo.clipKeywordsFormatted()
videoRole = marker.roles.videoFormatted()
audioRole = marker.roles.audioFormatted(multipleRoleSeparator: ",")
eventName = marker.parentInfo.eventName
projectName = marker.parentInfo.projectName
libraryName = marker.parentInfo.libraryName
eventName = marker.parentInfo.eventName ?? ""
projectName = marker.parentInfo.projectName ?? ""
libraryName = marker.parentInfo.libraryName ?? ""
icon = Icon(marker.type)

// self.mediaInfo = mediaInfo
Expand All @@ -80,7 +80,7 @@ public struct StandardExportMarker: ExportMarker {

imageTimecode = marker.imageTimecode(
useChapterMarkerPosterOffset: useChapterMarkerPosterOffset,
offsetToProjectStart: offsetToProjectStart
offsetToTimelineStart: offsetToTimelineStart
)
}
}
Loading

0 comments on commit f7007e3

Please sign in to comment.