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

Exported video appears to be darker (colour shifting) #84

Open
m-at-drigmo opened this issue Mar 7, 2022 · 4 comments
Open

Exported video appears to be darker (colour shifting) #84

m-at-drigmo opened this issue Mar 7, 2022 · 4 comments

Comments

@m-at-drigmo
Copy link

m-at-drigmo commented Mar 7, 2022

I noticed that while exporting video using AVAssetExportSession, the result appears to be darker.
Attached below are the original and exported screenshot of the videos.

Is this expected? Any suggestions/workarounds to preserve as much of the visual quality of the original videos in the exported?

Original:
IMG_0876

Exported:
IMG_0877

The code:

        let timeline = Timeline()
        
        var videoChannels = [TrackItem]()
        var audioChannels = [TrackItem]()
        
        var currentTime = CMTime.zero
        for asset in self.assets {
            let resource = AVAssetTrackResource(asset: asset)

            let trackItem = TrackItem(resource: resource)
            trackItem.videoConfiguration.contentMode = .aspectFit
            trackItem.startTime = currentTime
            currentTime = CMTimeAdd(currentTime, asset.duration)
            
            videoChannels.append(trackItem)
            audioChannels.append(trackItem)
        }
        
        timeline.videoChannel = videoChannels
        timeline.audioChannel = audioChannels
        timeline.renderSize = CGSize(width: 1080, height: 1920)

        let compositionGenerator = CompositionGenerator(timeline: timeline)
        let exportSession = compositionGenerator.buildExportSession(presetName: AVAssetExportPresetHighestQuality)
        exportSession?.outputFileType = .mov

        let outputURL = URL(fileURLWithPath: NSTemporaryDirectory().appending("test.mov"))
        exportSession?.outputURL = outputURL
        exportSession?.exportAsynchronously {
            if let error = exportSession?.error {
                print("Failed to export: \(error)")
            } else {
                print("Movie file generated: \(outputURL)")
            }
        }
@m-at-drigmo
Copy link
Author

Upon further digging, this appears to be HDR related issue.

The original is an HDR video, and it looks like the exported video did not preserve the HDR format.
Per Apple's WWDC sessions for exporting HDR, AVAssetExportSession will preserve HDR without extra code if default compositor is used (and the chosen preset is set to one of the AVAssetExportPresetHEVC* options).

When using custom compositor though (which is the case for Cabbage), it must be updated to be HDR aware.

I have tried rewriting the code above to use AVFoundation APIs directly, the video is exported correctly when HEVC preset is used.

@vitoziv
Copy link
Contributor

vitoziv commented Mar 21, 2022

I add a demo to show how to support HDR video, you can pull the latest code.

41c7870#diff-2dc4dc28f7aa306658725e96363ac9a93d6e8642d3435f0b5a15407b463ed796R128

HDR could be supported by subclass VideoCompositor

@huanglins
Copy link

预览正常,导出存在偏色,我这边测试的视频是偏红😭

@larryonoff
Copy link

@m-at-drigmo we have fixed this issue in our local code. Steps that you should do.

  1. check that timeline has HDR video
extension AVAsset {
  @inlinable
  public var containsHDRVideo: Bool {
    tracks.contains { $0.hasMediaCharacteristic(.containsHDRVideo) }
  }
}

extension AVAssetTrackResource {
  public var containsHDRVideo: Bool {
    asset?.containsHDRVideo ?? false
  }
}

extension Timeline {
    public var containsHDRVideo: Bool {
      return videoChannel.contains { channel in
        guard let item = channel as? TrackItem else {
          return false
        }
        guard let assetTrackResource = item.resource as? AVAssetTrackResource else {
          return false
        }
        return assetTrackResource.containsHDRVideo
      }
    }
}
  1. Set HDRVideoCompositor for AVVideoComposition when timeline.containsHDRVideo == true
  2. Use AVAssetExportPresetHEVC1920x1080 for AVVideoComposition when timeline.containsHDRVideo == true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants