@@ -1769,11 +1769,17 @@ async fn import_and_upload_video(
17691769 source_path : PathBuf ,
17701770 channel : Channel < UploadProgress > ,
17711771) -> Result < UploadResult , String > {
1772- // 1) Auth/plan checks (reuse code from upload_exported_video)
1773- let Ok ( Some ( auth) ) = AuthStore :: get ( & app) else {
1774- AuthStore :: set ( & app, None ) . map_err ( |e| e. to_string ( ) ) ?;
1775- return Ok ( UploadResult :: NotAuthenticated ) ;
1776- } ;
1772+ // Importing always requires Pro
1773+ {
1774+ let Ok ( Some ( auth) ) = AuthStore :: get ( & app) else {
1775+ AuthStore :: set ( & app, None ) . map_err ( |e| e. to_string ( ) ) ?;
1776+ return Ok ( UploadResult :: NotAuthenticated ) ;
1777+ } ;
1778+
1779+ if !auth. is_upgraded ( ) {
1780+ return Ok ( UploadResult :: UpgradeRequired ) ;
1781+ }
1782+ }
17771783
17781784 // Validate source file exists and is a valid video
17791785 if !source_path. exists ( ) {
@@ -1788,10 +1794,6 @@ async fn import_and_upload_video(
17881794 let source_metadata = build_video_meta ( & source_path)
17891795 . map_err ( |err| format ! ( "Error getting source video meta: {err}" ) ) ?;
17901796
1791- if !auth. is_upgraded ( ) && source_metadata. duration_in_secs > 300.0 {
1792- return Ok ( UploadResult :: UpgradeRequired ) ;
1793- }
1794-
17951797 // 2) Create new project dir
17961798 let id = uuid:: Uuid :: new_v4 ( ) . to_string ( ) ;
17971799 let recording_dir = recordings_path ( & app) . join ( format ! ( "{id}.cap" ) ) ;
@@ -1930,6 +1932,7 @@ async fn transcode_to_mp4(input: &Path, output: &Path) -> Result<(), String> {
19301932 . ok_or_else ( || "No video stream found in input file" . to_string ( ) ) ?;
19311933
19321934 let video_stream_index = video_stream. index ( ) ;
1935+ let input_time_base = video_stream. time_base ( ) ;
19331936
19341937 let mut octx = ffmpeg:: format:: output ( & output)
19351938 . map_err ( |e| format ! ( "Failed to create output context: {e}" ) ) ?;
@@ -1942,6 +1945,7 @@ async fn transcode_to_mp4(input: &Path, output: &Path) -> Result<(), String> {
19421945 . format ( )
19431946 . flags ( )
19441947 . contains ( ffmpeg:: format:: flag:: Flags :: GLOBAL_HEADER ) ;
1948+
19451949 let mut encoder = ffmpeg:: codec:: context:: Context :: new_with_codec ( codec)
19461950 . encoder ( )
19471951 . video ( )
@@ -1954,12 +1958,26 @@ async fn transcode_to_mp4(input: &Path, output: &Path) -> Result<(), String> {
19541958 . video ( )
19551959 . map_err ( |e| format ! ( "Failed to create video decoder: {e}" ) ) ?;
19561960
1957- // Configure encoder
1961+ // Configure encoder with proper settings
19581962 encoder. set_width ( decoder. width ( ) ) ;
19591963 encoder. set_height ( decoder. height ( ) ) ;
19601964 encoder. set_format ( ffmpeg:: format:: Pixel :: YUV420P ) ;
1961- encoder. set_frame_rate ( Some ( ffmpeg:: Rational :: from ( ( 30 , 1 ) ) ) ) ; // 30fps as per spec
1962- encoder. set_time_base ( ffmpeg:: Rational :: from ( ( 1 , 30 ) ) ) ;
1965+
1966+ // Use input stream frame rate or fallback to 30fps
1967+ let fps = {
1968+ let stream_fps = video_stream. avg_frame_rate ( ) ;
1969+ if stream_fps. numerator ( ) > 0 && stream_fps. denominator ( ) > 0 {
1970+ stream_fps
1971+ } else {
1972+ ffmpeg:: Rational :: from ( ( 30 , 1 ) )
1973+ }
1974+ } ;
1975+ encoder. set_frame_rate ( Some ( fps) ) ;
1976+ encoder. set_time_base ( fps. invert ( ) ) ;
1977+
1978+ // Set quality parameters
1979+ encoder. set_bit_rate ( decoder. bit_rate ( ) . max ( 1_000_000 ) ) ; // At least 1Mbps
1980+ encoder. set_max_b_frames ( 0 ) ; // Disable B-frames for compatibility
19631981
19641982 if global_header {
19651983 encoder. set_flags ( ffmpeg:: codec:: flag:: Flags :: GLOBAL_HEADER ) ;
@@ -1975,8 +1993,9 @@ async fn transcode_to_mp4(input: &Path, output: &Path) -> Result<(), String> {
19751993
19761994 output_stream. set_parameters ( & encoder) ;
19771995 let output_stream_index = output_stream. index ( ) ;
1978- let output_stream_time_base = output_stream. time_base ( ) ;
1996+ let output_time_base = output_stream. time_base ( ) ;
19791997
1998+ // Write header before processing
19801999 octx. write_header ( )
19812000 . map_err ( |e| format ! ( "Failed to write header: {e}" ) ) ?;
19822001
@@ -1991,12 +2010,16 @@ async fn transcode_to_mp4(input: &Path, output: &Path) -> Result<(), String> {
19912010 )
19922011 . map_err ( |e| format ! ( "Failed to create scaler: {e}" ) ) ?;
19932012
1994- let mut frame_index = 0 ;
19952013 let mut decoded_frame = ffmpeg:: frame:: Video :: empty ( ) ;
19962014 let mut encoded_frame = ffmpeg:: frame:: Video :: empty ( ) ;
2015+ let mut output_frame_count = 0i64 ;
19972016
1998- for ( stream, packet) in ictx. packets ( ) {
2017+ // Process packets
2018+ for ( stream, mut packet) in ictx. packets ( ) {
19992019 if stream. index ( ) == video_stream_index {
2020+ // Rescale packet timestamp to decoder time base
2021+ packet. rescale_ts ( input_time_base, decoder. time_base ( ) ) ;
2022+
20002023 decoder
20012024 . send_packet ( & packet)
20022025 . map_err ( |e| format ! ( "Failed to send packet to decoder: {e}" ) ) ?;
@@ -2006,17 +2029,30 @@ async fn transcode_to_mp4(input: &Path, output: &Path) -> Result<(), String> {
20062029 . run ( & decoded_frame, & mut encoded_frame)
20072030 . map_err ( |e| format ! ( "Failed to scale frame: {e}" ) ) ?;
20082031
2009- encoded_frame. set_pts ( Some ( frame_index) ) ;
2010- frame_index += 1 ;
2032+ // Set proper PTS for encoded frame
2033+ encoded_frame. set_pts ( Some ( output_frame_count) ) ;
2034+ output_frame_count += 1 ;
20112035
20122036 encoder
20132037 . send_frame ( & encoded_frame)
20142038 . map_err ( |e| format ! ( "Failed to send frame to encoder: {e}" ) ) ?;
20152039
2040+ // Flush encoder packets
20162041 let mut encoded_packet = ffmpeg:: packet:: Packet :: empty ( ) ;
20172042 while encoder. receive_packet ( & mut encoded_packet) . is_ok ( ) {
20182043 encoded_packet. set_stream ( output_stream_index) ;
2019- encoded_packet. rescale_ts ( encoder. time_base ( ) , output_stream_time_base) ;
2044+
2045+ // Properly rescale timestamps
2046+ encoded_packet. rescale_ts ( encoder. time_base ( ) , output_time_base) ;
2047+
2048+ // Ensure valid timestamps
2049+ if encoded_packet. pts ( ) . is_none ( ) {
2050+ encoded_packet. set_pts ( Some ( 0 ) ) ;
2051+ }
2052+ if encoded_packet. dts ( ) . is_none ( ) {
2053+ encoded_packet. set_dts ( encoded_packet. pts ( ) ) ;
2054+ }
2055+
20202056 encoded_packet
20212057 . write_interleaved ( & mut octx)
20222058 . map_err ( |e| format ! ( "Failed to write packet: {e}" ) ) ?;
@@ -2025,6 +2061,41 @@ async fn transcode_to_mp4(input: &Path, output: &Path) -> Result<(), String> {
20252061 }
20262062 }
20272063
2064+ // Flush decoder
2065+ decoder
2066+ . send_eof ( )
2067+ . map_err ( |e| format ! ( "Failed to flush decoder: {e}" ) ) ?;
2068+
2069+ while decoder. receive_frame ( & mut decoded_frame) . is_ok ( ) {
2070+ scaler
2071+ . run ( & decoded_frame, & mut encoded_frame)
2072+ . map_err ( |e| format ! ( "Failed to scale frame: {e}" ) ) ?;
2073+
2074+ encoded_frame. set_pts ( Some ( output_frame_count) ) ;
2075+ output_frame_count += 1 ;
2076+
2077+ encoder
2078+ . send_frame ( & encoded_frame)
2079+ . map_err ( |e| format ! ( "Failed to send frame to encoder: {e}" ) ) ?;
2080+
2081+ let mut encoded_packet = ffmpeg:: packet:: Packet :: empty ( ) ;
2082+ while encoder. receive_packet ( & mut encoded_packet) . is_ok ( ) {
2083+ encoded_packet. set_stream ( output_stream_index) ;
2084+ encoded_packet. rescale_ts ( encoder. time_base ( ) , output_time_base) ;
2085+
2086+ if encoded_packet. pts ( ) . is_none ( ) {
2087+ encoded_packet. set_pts ( Some ( 0 ) ) ;
2088+ }
2089+ if encoded_packet. dts ( ) . is_none ( ) {
2090+ encoded_packet. set_dts ( encoded_packet. pts ( ) ) ;
2091+ }
2092+
2093+ encoded_packet
2094+ . write_interleaved ( & mut octx)
2095+ . map_err ( |e| format ! ( "Failed to write packet: {e}" ) ) ?;
2096+ }
2097+ }
2098+
20282099 // Flush encoder
20292100 encoder
20302101 . send_eof ( )
@@ -2033,7 +2104,15 @@ async fn transcode_to_mp4(input: &Path, output: &Path) -> Result<(), String> {
20332104 let mut encoded_packet = ffmpeg:: packet:: Packet :: empty ( ) ;
20342105 while encoder. receive_packet ( & mut encoded_packet) . is_ok ( ) {
20352106 encoded_packet. set_stream ( output_stream_index) ;
2036- encoded_packet. rescale_ts ( encoder. time_base ( ) , output_stream_time_base) ;
2107+ encoded_packet. rescale_ts ( encoder. time_base ( ) , output_time_base) ;
2108+
2109+ if encoded_packet. pts ( ) . is_none ( ) {
2110+ encoded_packet. set_pts ( Some ( 0 ) ) ;
2111+ }
2112+ if encoded_packet. dts ( ) . is_none ( ) {
2113+ encoded_packet. set_dts ( encoded_packet. pts ( ) ) ;
2114+ }
2115+
20372116 encoded_packet
20382117 . write_interleaved ( & mut octx)
20392118 . map_err ( |e| format ! ( "Failed to write final packet: {e}" ) ) ?;
0 commit comments