ビデオレンダリング甚のホヌムファヌムの䜜成

この蚘事では、自宅でビデオをレンダリングするための別のサヌバヌ「ファヌム」は既に倧声で蚀われおいたすを䜜成した経隓に぀いお説明したす。









ご存知のように、ビデオず3D画像のレンダリングには時間がかかり、倚くのコンピュヌタヌリ゜ヌスが必芁です。 思い出はただ新鮮です。孊生の頃、倜に映画䜜成プログラムを実行しながら賑やかなコンピュヌタヌをセットアップしたしたが、午前䞭にハヌドドラむブに十分なスペヌスがないか、ビデオに䜕かを远加するのを忘れお、すべおを最初からやり盎す必芁がありたした。 珟圚、真のプロフェッショナルがこの操䜜をリモヌトで実行しおいたす。 たずえば、監督のゞェヌムズキャメロンは、映画「アバタヌ」の撮圱䞭に、シヌンのレンダリングが開始されるデヌタセンタヌ党䜓を䜜成するよう特に呜じたした。 私はただ自分のデヌタセンタヌを構築するほどクヌルではありたせんが、この操䜜を別のサヌバヌで個別に起動できるずいう考えから、長い間平穏を埗るこずができたせんでした。



2番目の問題は、ビデオ自䜓の線集です。 珟代のコンピュヌタヌがより匷力になっおいるずいう事実にもかかわらず、ビデオカメラの開発も止たっおおらず、結果のビデオファむルはたすたす重くなっおいたす。 そしお、結果ずしお、それらを凊理するこずは問題になりたす。 長いフィルムを線集するず、フィルタヌずトランゞションが適甚されたトラックのプレビュヌがプロセッサヌの読み蟌みを開始し、画像が遅れ始め、クリ゚むティブな線集プロセスが面倒になりたす。 私が詊したこずから、最も生産的なのはiMovieで、これはすべおのMacにプリむンストヌルされおいたす。 45分間続く映画でさえ、比范的䜎電力のMacbookでは問題なく線集できたした。 任意のフィルタヌを適甚しお、遅れなくプレビュヌりィンドりで結果を確認できたす。 それで、ケシの所有者はここで幞運でした。 iMovieの欠点の1぀は、操䜜䞭に、途方もない量のディスクスペヌスを消費し始めるこずです。 どうやら、これは線集ずプレビュヌのための積極的なキャッシュによるものです。



この蚘事では、ホヌムビデオクリップの䟋を䜿甚しお、線集ずレンダリングのこれら2぀の問題を解決しようずしたずきの経隓を説明したす。



楜噚



Kdenliveロゎ



Linux甚のWindowsやMac OSず比范するず、原則ずしお、デスクトップアプリケヌションはそれほど倚くありたせんが、ビデオ゚ディタヌの遞択肢は驚くほど広いこずがわかりたした。 いく぀かのオプションで遊んだ埌、今のずころ私はKdenliveで小さなビデオを扱うこずに決めたした。 他のプログラムず比范するず、そこには優れた機胜セットがありたすが、この蚘事のフレヌムワヌクでは1぀だけに興味がありたすが、玠晎らしい機胜です既に完成したフィルムを倉換するずき、プログラムには2぀のオプションがありたす-通垞どおり、ファむルにレンダリングするか、スクリプトを生成したす。



KDenliveを䜿甚しお、スクリプトを生成する



この堎合、圌女は通垞のシェルスクリプトを䜜成するだけで、埌でコマンドラむンから実行できたす。 別のコンピュヌタヌを含む。 私は䜕を埗おいたすか はい、この方法でプロゞェクトをリモヌトサヌバヌに瞮小できたす。 これを行うには、クラりド、独自のサヌバヌ、たたはオフィスで垞に皌働しおいる匷力な䜜業コンピュヌタヌを䜿甚できたすもちろん、私はそうは蚀いたせんでした。 蚈画は単玔です。プロゞェクトを削枛し、スクリプトを生成し、プロゞェクト党䜓をサヌバヌに転送し、プロセスをリモヌトで開始したす。



しかし、それは本圓のバむ゜ンには簡単すぎるように思えたす。 タスクにいく぀かの条件を远加したす。 元のビデオファむルの線集は倚くのリ゜ヌスを必芁ずするタスクであるずすでに䞍満を蚀っおいたす。 䜜業䞭、小さなプレビュヌりィンドりで結果を確認し、個々のストヌリヌを䜕十回もスクロヌルし、字幕を調敎し、フィルタヌを倉曎し、䌎奏を远加したす。 しかし、小さなビデオファむルを䜿甚しおプロゞェクトをマりントし、元のファむルで既に最終アセンブリを実行しおいる堎合はどうでしょうか。 ずにかく、操䜜䞭に党画面プレビュヌを開くこずはほずんどありたせん。 芁玄するず、プロセスは次のようになりたす。



  1. ビデオ゜ヌスごずに、軜量のクロヌンを䜜成したす。
  2. オリゞナルをサヌバヌに転送したす。
  3. むンストヌルは、軜量コピヌを䜿甚しおパヌ゜ナルコンピュヌタヌに実行されたすラップトップを䜿甚したした。
  4. 組み立おる前に、プロゞェクトをサヌバヌに転送したす。サヌバヌには、元の品質の゜ヌスコヌドが既にありたす。
  5. 軜量クロヌンを元のクロヌンに眮き換えたす。
  6. フィルムの高解像床でのレンダリングを開始したす。
  7. オプション電子メヌルたたはSMSでプロセスの完了を通知したす。
  8. 完成した結果をパ゜コンにダりンロヌドしたす。
  9. 完成したビデオおよび自分のスキルをドラッグしたす。




たず最初に。



軜量コピヌ



Linuxの堎合、ビデオを倉換および圧瞮するためのかなり人気のあるプログラム-HandBrakeがありたす。 タスクは単に゜ヌスコヌドを圧瞮するこずなので、蚭定に぀いおはあたり考えず、既成のプリセットを䜿甚したす。 良い結果リコヌル、家庭甚ビデオを提䟛するiPodを遞択し、゜ヌスの圧瞮を詊みたす。







玠晎らしい䌑暇の埌、これらの゜ヌスを䜕癟ずは蚀わないたでも数十個持぀こずがあり、この䜜業を䜕らかの圢で自動化する必芁がある堎合がありたす。 具䜓的には、HandBrakeには独自のコマンドむンタヌフェむスがありたす 。 したがっお、次のようなスクリプトをすばやく実行できたす。



#!/bin/bash # convert.sh quality=30 for file in ls $1/* do tempfile="${file##*/}" filename="${tempfile%.*}" outputFile="$2/$filename.mp4" echo -e "\n\n Compress file $file" HandBrakeCLI -i $file -o $outputFile --preset="iPod" -q $quality -w 160 done
      
      





convert.sh ./original-videos ./small-videosコマンドを䜿甚しお実行するこずにより、各ファむルに察しおより小さく最適化されたコピヌを䜜成したす。 唯䞀の条件は、将来私たちの生掻を楜にするこずです。すべおのファむルずそのクロヌンが同じ名前を持぀こずに同意したすただし、ほずんどの堎合、拡匵子は異なりたす。 これが私がしたこずの䟋です。 2぀のフォルダヌ



 /小動画/オリゞナル動画
 FILE0001.mp4 FILE0001.MOV
 FILE0002.mp4 FILE0002.MOV
 FILE0003.mp4 FILE0003.MOV
 ... ...




したがっお、名前を䜿甚しお、プログラムでコピヌを元のコピヌに眮き換えるこずができたす。 その埌、元のビデオのあるフォルダヌがサヌバヌに送信され、小さなコピヌがラップトップに残り、さらに䜜業を続けたす。



元のビデオずその軜量クロヌンの䟋







うヌん...私は圧瞮で行き過ぎたしたか すべおは実隓の玔床のためです



プロゞェクト



そのため、プロゞェクトを開始したした。 もちろん、プレビュヌの品質は䞍快ですが、䜕をすべきかです。すべおの䜜業の速床を萜ずす䞋劣な遅れを取り陀きたいず考えたした。 泣き続けお泚入しながら、フィルムをマりントしたす。 特にプロセッサに負担をかけるこずなく、すべおがスマヌトに機胜したす。 重芁な瞬間情報の時が来たした。 倧切なボタンGenerate Script ...を抌しお、結果を保存したす。 次に、䜕が起きたのか、プログラムが䞀般的に䜕を保存したのかを芋おみたしょう。



Kdenliveタむムラむン



2぀のファむルがKDEnliveホヌムフォルダヌに衚瀺されたしたデフォルトは〜/ kdenlive / scripts / 

  1. シェルスクリプトmy-movie_001.sh
  2. my-movie_001.sh.mltをファむルしたす


シェルファむルmy-movie_001.shには、短いコマンドセットがありたす。



 #! /bin/sh SOURCE="/home/w32blaster/kdenlive/scripts/my-movie_001.sh.mlt" TARGET="/home/w32blaster/kdenlive/my-movie.mp4" RENDERER="/usr/bin/kdenlive_render" MELT="/usr/bin/melt" PARAMETERS="-pid:8613 $MELT hdv_1080_50i avformat - $SOURCE $TARGET properties=x264-medium g=120 crf=20 ab=160k threads=1 real_time=-1" $RENDERER $PARAMETERS
      
      





ここには特別なストリヌトマゞックはありたせん。パスず蚭定を保存するだけで、必芁なパラメヌタヌでレンダリングを開始したす。 必芁に応じお線集できたすが、1぀のパラメヌタヌ「threads = 1」に泚意しおください。これは、ご想像のずおり、スレッドの数を蚭定したす。 プロセッサのパワヌに応じお、この数を増やすこずができ、レンダリングパフォヌマンスが倧幅に向䞊したす。 さらに、ラップトップをロヌドせずに、より匷力なコンピュヌタヌで実行したす。



ただし、この実隓で特に興味深いのは、意味のある宣蚀でマヌクされた別のファむルです。



 SOURCE = "/ home / w32blaster / kdenlive / scripts / my-movie_001.sh.mlt"


これはどのようなMLTファむルですか



MLTずプロゞェクトの説明



MLTロゎ



少なくずも私にずっおはオヌプン゜ヌス゜フトりェアの䞖界には、ビデオブロヌドキャストを送信するためのそのような圢匏ず、 MLTず呌ばれる同じ名前のフレヌムワヌクがあるこずがわかりたした 。 サむトは次のように蚀っおいたす



MLTは、テレビ攟送甚に蚭蚈および開発されたオヌプン゜ヌスのマルチメディアフレヌムワヌクです。 攟送局、ビデオ線集者、メディアプレヌダヌ、トランスコヌダヌ、Webストリヌマヌ、およびその他の倚くの皮類のアプリケヌションにツヌルキットを提䟛したす。 システムの機胜は、すぐに䜿甚できる各皮のツヌル、XMLオヌサリングコンポヌネント、および拡匵可胜なプラグむンベヌスのAPIを介しお提䟛されたす。




コン゜ヌルプログラムMeltを䜿甚するず、ビデオプロゞェクトをコン゜ヌルに盎接たずめるこずができたす。 ぀たり、理論的には、コン゜ヌルを離れるこずなく映画党䜓を䜜成するこずさえできたす。 そのためには、キロメヌトルのチヌムを䜜成しお実行する必芁がありたすが、もちろん倧倚数のチヌムはそれを奜みたせん。 代わりに、プロゞェクト党䜓が、ナビキタスXMLに基づく特別なMLT圢匏で蚘述されおいたす。 したがっお、ビデオレンダリングは、将来の映画のパラメヌタヌずプロゞェクト自䜓の䞡方をMLT圢匏で䟛絊するメルトコン゜ヌルプログラムの起動です。 MLTファむル自䜓は、GUIプログラムによっお生成されたす。 私の堎合、私が蚀ったように、それはKDenliveでした。 このナヌティリティをオフドックで䜿甚する方法の詳现をお読みください。



ここで、ムヌビヌから生成されたMLTファむル自䜓の構造を芋おみたしょう。



 <?xml version='1.0' encoding='utf-8'?> <mlt title="Anonymous Submission" version="0.9.3" root="/home/w32blaster" LC_NUMERIC="en_GB.UTF-8"> <producer in="0" out="5367" id="117_4"> <property name="resource">Videos/small/FILE0001.mp4</property> ...    - </producer> <playlist id="playlist1"> <entry in="0" out="2033" producer="117_4"> <filter out="1838" id="volume"> ...   ... </filter> </playlist> <tractor title="Anonymous Submission" global_feed="1" in="0" out="17018" id="maintractor"> <property name="meta.volume">1</property> <track producer="black_track"/> <track hide="video" producer="playlist1"/> <track hide="video" producer="playlist2"/> <track producer="playlist3"/> <track producer="playlist4"/> <track producer="playlist5"/> <transition id="transition0"> <property name="a_track">1</property> <property name="b_track">2</property> <property name="mlt_type">transition</property> <property name="mlt_service">mix</property> <property name="always_active">1</property> <property name="combine">1</property> <property name="internal_added">237</property> </transition> .... - ,     .... </tractor> </mlt>
      
      





ボリュヌムず明らかな混乱にもかかわらず、このファむルはかなり単玔な構造をしおいたす。







mltファむルの構造の詳现に぀いおは、 こちらをご芧ください 。



そこで、最初のmltファむルを生成したした。このファむルには、圧瞮されたビデオクロヌンで構成されるフィルム自䜓の構造が含たれたす。 ムヌビヌをレンダリングする準備ができるたびに、この構造を持぀このファむルを生成したす。 クラむアント偎぀たりラップトップでプロゞェクトがどうなるかがわかったようです。今床は、サヌバヌ䞊でこれを操䜜する方法を把握しおから、それ自䜓をレンダリングする必芁がありたす。 蚈画では、mltファむル内のすべおの「プロデュヌサヌ」を、たったく同じであるが元のビデオの小さなビデオに眮き換えおから、アセンブリを開始する前にミキシングを開始したす。 理想的には、だれも眮換に気付かないでしょう。



この操䜜では、どの小さなファむルが倧きなオリゞナルに察応するかを芋぀ける必芁がありたす。 問題は、「プロデュヌサヌ」がビデオクリップの技術デヌタを䜿甚するずいう事実によっお耇雑になりたす。 それらの1぀の䟋を次に瀺したす。



 <producer in="0" out="1327" id="65_2"> <property name="mlt_type">producer</property> <property name="length">1328</property> <property name="eof">pause</property> <property name="resource">Videos/Austria2015-small/FILE1235.mp4</property> <property name="meta.media.nb_streams">2</property> <property name="meta.media.0.stream.type">video</property> <property name="meta.media.0.stream.frame_rate">30</property> <property name="meta.media.0.stream.sample_aspect_ratio">0</property> <property name="meta.media.0.codec.width">160</property> <property name="meta.media.0.codec.height">90</property> <property name="meta.media.0.codec.frame_rate">90000</property> <property name="meta.media.0.codec.pix_fmt">yuv420p</property> <property name="meta.media.0.codec.sample_aspect_ratio">0</property> <property name="meta.media.0.codec.colorspace">709</property> <property name="meta.media.0.codec.color_trc">1</property> <property name="meta.media.0.codec.name">h264</property> <property name="meta.media.0.codec.long_name">H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10</property> <property name="meta.media.0.codec.bit_rate">52987</property> <property name="meta.media.1.stream.type">audio</property> <property name="meta.media.1.codec.sample_fmt">fltp</property> <property name="meta.media.1.codec.sample_rate">48000</property> <property name="meta.media.1.codec.channels">2</property> <property name="meta.media.1.codec.name">aac</property> <property name="meta.media.1.codec.long_name">AAC (Advanced Audio Coding)</property> <property name="meta.media.1.codec.bit_rate">163117</property> <property name="meta.attr.1.stream.language.markup">eng</property> <property name="meta.attr.major_brand.markup">mp42</property> <property name="meta.attr.minor_version.markup">512</property> <property name="meta.attr.compatible_brands.markup">isomiso2avc1</property> <property name="meta.attr.encoder.markup">HandBrake 0.10.1 2015030800</property> <property name="seekable">1</property> <property name="meta.media.sample_aspect_num">1</property> <property name="meta.media.sample_aspect_den">1</property> <property name="aspect_ratio">1</property> <property name="audio_index">1</property> <property name="video_index">0</property> <property name="mlt_service">avformat</property> <property name="meta.media.frame_rate_num">30</property> <property name="meta.media.frame_rate_den">1</property> <property name="meta.media.colorspace">709</property> <property name="meta.media.width">160</property> <property name="meta.media.height">90</property> <property name="meta.media.top_field_first">0</property> <property name="meta.media.progressive">1</property> <property name="meta.media.color_trc">1</property> </producer>
      
      





悪くないよね 䜕らかの方法でこれらのリ゜ヌスパラメヌタをすべお眮き換える必芁があり、できれば手動で眮き換える必芁はありたせん。 この問題は、mltのスキヌムがないずいう事実によっおさらに耇雑になるため、ファむルの正確さを怜蚌するのはプログラム的に困難です。 チャンスを取り、スキヌムなしでやっおみおください。



クロヌンのメタデヌタを元のデヌタに眮き換えるにはどうすればよいでしょうかもちろん、ビデオ自䜓が異なるため、これは異なりたす。 幞いなこずに、メルトは正しいmltを䜜るのに十分賢く、圌自身が埌で消費したす。 meltコマンドを䜿甚しおレンダリングを開始するずき、デヌタ゜ヌス䞊蚘のように「プロデュヌサヌ」ずストリヌムがリダむレクトされるコンシュヌマヌ「コンシュヌマヌ」を指定する必芁がありたす。 コンシュヌマは異なる堎合があり、すべおのオプションはここで衚瀺するか、コン゜ヌルからコマンドを入力するこずで衚瀺できたす。



 $ melt -query "consumers" --- consumers: - decklink - xgl - qglsl - sdl - sdl_audio - sdl_preview - sdl_still - cbrts - xml - sdi - jack - avformat - multi - null - gtk2_preview - blipflash - rtaudio ...
      
      





ご芧のずおり、レンダリング出力を任意のものにリダむレクトできたす。 たずえば、ファむルぞの通垞のレンダリング䞭に、avformatが䜿甚されたす。 マりントするものはすべお1぀のファむルに保存されたす。 2番目の䟋ずしお、次のコマンドを䜿甚しお、すぐに出力をstdoutに送るこずができたす。



 $ melt original.mlt -consumer libdv




その埌、ビデオ再生のあるりィンドりが開き、溶けおフィルムが瞮小され、その間、開いおいるりィンドりにその堎でリダむレクトされたす。







ただし、 「xml」をコンシュヌマずしお指定し、ビデオファむルを゜ヌスずしお指定するず、meltはすべおのファむルずその技術パラメヌタヌをリストし、すべおのコンテンツをXML圢匏で矎しくフォヌマットされたMLTファむルに出力したす。 コマンドの䟋を次に瀺したす。



 $ melt * .MOV -consumer xmloriginal.mlt




解像床MOVのこのディレクトリにあるビデオファむルの「プロデュヌサヌ」のみを含むMLTファむルを生成したす。 圓然、元の倧きなビデオファむルの正しいメタデヌタを䜿甚したす。 これが私たちの陰湿な蚈画に必芁なものです だから



  1. サヌバヌ䞊の元の堎所を知っおいたす。
  2. これらのオリゞナルに基づいお、オリゞナルのビデオずそのメタデヌタを含む「プロデュヌサヌ」を1぀だけ含むMLTファむルをコマンドラむンで生成したす。 original.mltず呌びたしょう。 このファむルには映画の説明぀たりトラクタヌタグは含たれず、1぀の゜ヌスのみが含たれたす。 いわゆるの゜ヌスずしお䜿甚したす 正しい「プロデュヌサヌ」。
  3. 珟圚のMLTファむルをラップトップからサヌバヌに転送したす。サヌバヌには、珟圚の倉曎が加えられた映画が含たれおいたすが、「コピヌされた」小さなコピヌが含たれおいたす。 small.mltず呌びたしょう
  4. オリゞナルずコピヌは同じ名前ただし、拡匵子は異なる可胜性があるを念頭に眮いお、最初のMLTファむルの「正しい」プロデュヌサヌず2番目のMLTファむルの「トリミングされた」プロデュヌサヌを䞀臎させるこずができたす。
  5. プロデュヌサヌ自䜓だけでなく、おそらくIDも異なるため、IDも眮き換える必芁がありたす。
  6. 曞き始めるこずができたす。




その結果、各プロデュヌサヌは次のようになりたす。



  <producer> <property name="resource">Videos/small/FILE1234.mp4</property> ...  - </producer>
      
      







次のようなプロデュヌサヌに眮き換える必芁がありたす。



  <producer> <property name="resource">Videos/original/FILE1234.MOV</property> ...  - </producer>
      
      





この操䜜を完了するために、 テスト付きの小さなPython スクリプトをスケッチしたした。 実際、私はJavaの信者なので、これが私の最初のPythonコヌドです。 読んだ埌、私の曲がった手をたっすぐにする必芁があるこずがわかった堎合、あなたの考えや提案はプルリク゚ストの圢で歓迎されたす。



リスト1MLTファむルハンドラヌコヌド
 #!/usr/bin/env python import xml.etree.ElementTree as ET import os.path import sys, getopt def main(argv): ''' The main purpose of this programm is to take the given MLT file containing producers with an compressed ("small") resources (video, images, sound) and replace them with identical producers with uncompressed ("original") resources from another MLT file Example of usage: python process.py -s ~/Videos/small.sh.mlt -p ~/Videos/original/original.mlt ''' smallVideosFile, originalVideosFile, homeDir = _extractCLArguments(argv) if (smallVideosFile == '' or originalVideosFile == ''): print "Error. Both arguments -s and -p must be provided!" sys.exit(2) print "Start MLT file processor. We will modify %s using data from %s" % (smallVideosFile, originalVideosFile) # Parse the MLT file with small resources smallTree = ET.parse(smallVideosFile) smallTreeRoot = smallTree.getroot() # and MLT file with original (big, full size) resources originalTree = ET.parse(originalVideosFile) originalTreeRoot = originalTree.getroot() # prepare maps "video file name" <==> "producer ID" mapSmallProducers = _getMapOfProducerIds(smallTreeRoot) mapOriginalProducers = _getMapOfProducerIds(originalTreeRoot) # build map "small producer ID" <==> "original producer ID", having the same video resource mapID = _mergeMaps(mapSmallProducers, mapOriginalProducers) # update 'root' value in MLT tag _updateRootTag(homeDir, smallTreeRoot) # then replace all the producers containing small videos with those with original videos _replaceAllSmallProducersWithOriginal(mapOriginalProducers, smallTreeRoot, originalTreeRoot) # print modified MLT to output file ET.ElementTree(smallTreeRoot).write(smallVideosFile, encoding='utf-8', xml_declaration=True) def _extractResourceName(fullName): ''' Extracts only the resource name from full path. For example, if the fullName is Videos/small/FILE1114.mkv this method returns FILE1114 ''' if "?" in fullName: withoutParam = fullName.split("?",1)[0] return os.path.splitext(os.path.basename(withoutParam))[0] else: return os.path.splitext(os.path.basename(fullName))[0] def _mergeMaps(mapSmallProducers, mapOriginalProducers): ''' Builds map of producer IDs: each small producer's ID should match appropriate big producer's ID, having the same resource. ''' mapID = {} for fileName, oldProducerId in mapSmallProducers.items(): if (fileName in mapOriginalProducers): mapID[oldProducerId] = mapOriginalProducers[fileName] return mapID def _getMapOfProducerIds(tree): ''' Builds the map for the given file: "resource (video file name)" <=> "producer ID". ''' arrProducers = tree.findall('producer') # Collect the map "resourse (video file name)" <==> "id of the producer" mapIdToResource = {} for producer in arrProducers: resourceType = producer.find("*[@name='mlt_service']").text isReplacementNeeded = (resourceType == "avformat" or resourceType == "framebuffer" or resourceType == "xml") if (isReplacementNeeded): resourceValue = producer.find("*[@name='resource']").text # extract only filename (without path and extension) fileName = _extractResourceName(resourceValue) mapIdToResource[fileName] = producer.attrib.get('id') else: print "[Ignored] the producer %s (resource type is %s) is ignored" % (producer.attrib.get('id'), resourceType) pass return mapIdToResource def _replaceAllSmallProducersWithOriginal(mapOriginalProducers, rootToBeModified, rootOriginal): ''' Replaces all DOM-element 'Producer' containing small resources with identical producers, containing the original resource ''' print "Replace old producer having small size with another one having original resource:" arrSmallProducers = rootToBeModified.findall('producer') for producer in arrSmallProducers: resourceType = producer.find("*[@name='mlt_service']").text if (resourceType == "avformat"): _replaceProducerAvformat(producer, mapOriginalProducers, rootToBeModified, rootOriginal) elif (resourceType == "framebuffer"): _replaceProducerFramebuffer(producer, mapOriginalProducers, rootToBeModified, rootOriginal) elif (resourceType == "xml"): _replaceProducerXml(producer, mapOriginalProducers, rootToBeModified, rootOriginal) def _replaceProducerAvformat(producer, mapOriginalProducers, rootToBeModified, rootOriginal): ''' Replace entirely one producer, containing small resource with similar producer from original tree. Resulting producer should have the same ID, but it must get all the values from original tree (URLs, codec properties and other technical information) ''' resourceValue = producer.find("*[@name='resource']").text fileName = _extractResourceName(resourceValue) if(fileName in mapOriginalProducers): # remember in, out and length from small producer attrIn = producer.attrib.get('in') attrOut = producer.attrib.get('out') length = producer.find("*[@name='length']").text producerId = producer.attrib.get('id') originalId = mapOriginalProducers[fileName] origProducer = rootOriginal.find('.//producer[@id="' + originalId + '"]') if origProducer is not None: rootToBeModified.remove(producer) # do not touch original node, deal with clone instead origProducerClone = origProducer.copy() # update in, out and length to match with small producer origProducerClone.set('in', attrIn) origProducerClone.set('out', attrOut) origProducerClone.set('id', producerId) origProducerClone.find("*[@name='length']").text = length rootToBeModified.insert(1, origProducerClone) print " - Avformat resource (id=%s) is replaced with resource (id=%s)" % (producerId, originalId) else: print " - [Ignored] Avformat resource (id=%s) was not found. File name is '%s' and found original ID is '%s'" % (producerId, fileName, originalId) def _replaceProducerFramebuffer(producer, mapOriginalProducers, rootToBeModified, rootOriginal): ''' Update given producer's resource. The resulting producer should have the same properties except resource path. Keep in mind, that we need to keep the parameter after "?" sign. ''' resourceNode = producer.find("*[@name='resource']") resourceValue = resourceNode.text producerId = producer.attrib.get('id') fileName = _extractResourceName(resourceValue) if(fileName in mapOriginalProducers): originalId = mapOriginalProducers[fileName] origProducer = rootOriginal.find('.//producer[@id="' + originalId + '"]') if origProducer is not None: originalResourcePath = origProducer.find("*[@name='resource']").text extension = resourceValue.split("?",1)[1] resourceNode.text = originalResourcePath + "?" + extension print " - Framebuffer resource (id=%s) is replaced with resource (id=%s)" % (producerId, originalId) else: print " - [Ignored] the Framebuffer resource (id=%s) is ignored!" % (producerId) def _replaceProducerXml(producer, mapOriginalProducers, rootToBeModified, rootOriginal): ''' Update given producer in case if it is XML resource. The resulting producer should have updated resource path including .mlt extension. ''' resourceNode = producer.find("*[@name='resource']") resourceValue = resourceNode.text[:-4] # trim .mlt extension producerId = producer.attrib.get('id') fileName = _extractResourceName(resourceValue) if(fileName in mapOriginalProducers): originalId = mapOriginalProducers[fileName] origProducer = rootOriginal.find('.//producer[@id="' + originalId + '"]') if origProducer is not None: originalResourcePath = origProducer.find("*[@name='resource']").text resourceNode.text = originalResourcePath + ".mlt" print " - XML resource (id=%s) is replaced with resource (id=%s)" % (producerId, originalId) def _updateRootTag(homedir, rootToBeModified): ''' In order to find all the resources, MLT uses the arggument "root" placed in tag MLT. When we work on different computers, we must also update this value in order MELT would be able to find resources. ''' if (homedir != ''): rootToBeModified.set('root', homedir) def _extractCLArguments(argv): inputfile = '' outputfile = '' homedir = '' try: opts, args = getopt.getopt(argv,"hs:p:u:",["smallfile=","producersfile=", "userhomedir="]) except getopt.GetoptError: print 'process.py -s <smallFileToBeModified> -p <producersFile>' sys.exit(2) for opt, arg in opts: if opt == '-h': print '''process.py -s <smallFile> -p <producersFile> -u <userHomeDir> where "smallFile" is a mlt file to be modified and "producersFile" is a mlt file containing the list of producers with original resources. ''' sys.exit() elif opt in ("-s", "--smallfile"): inputfile = arg elif opt in ("-p", "--producersfile"): outputfile = arg elif opt in ("-u", "--userhomedir"): homedir = arg return inputfile, outputfile, homedir if __name__ == "__main__": main(sys.argv[1:])
      
      









次のコマンドでこのスクリプトを実行したす。



 python process.py -s small.mlt -p original.mlt




「 original.mltファむルからすべおのプロデュヌサヌを取埗し、 small.mltファむル内の察応するプロデュヌサヌに眮き換えたすが、その他のプロデュヌサヌは倉曎しないでください」ず衚瀺されたす。



すべおをたずめる



さお、今床はプロゞェクトをリモヌトでアセンブルしおみたす。 Linuxにあるはずなので、サヌバヌ偎で理解しやすいシンプルなシェルスクリプトを䜜成したしょう。



リスト2完党なサヌバヌ偎スクリプト
 #!/bin/bash SMALL_RESORCES="Small" ORIGINAL_RESOURCES="Original" KDENLIVE_SCRIPT="austria-2015_001.sh" PY_SCRIPT="/home/ilya/home-workspace/mlt-producer-replacer/process.py" CURRENT_DIR="/home/ilya/Videos/MltProcessor" rm log echo -e "\n\n Step 1. Rename all the .mp4.mlt resources to .MOV.mlt" rm $ORIGINAL_RESOURCES/*.MOV.mlt for file in $ORIGINAL_RESOURCES/*.mlt; do cp "$file" "$ORIGINAL_RESOURCES/`basename $file .mp4.mlt`.MOV.mlt" done echo -e "\n\n Step 2. Generate fresh list of producers with original sources" rm $CURRENT_DIR/original.mlt cd ~ melt $CURRENT_DIR/$ORIGINAL_RESOURCES/*.{MOV,mp3} -consumer xml:original.mlt cd $CURRENT_DIR mv ~/original.mlt $CURRENT_DIR echo -e "\n\n Step 3. Update MLT and replace small videos with original ones" # process the main MLT file cp $KDENLIVE_SCRIPT.mlt $KDENLIVE_SCRIPT.mlt-BACKUP python $PY_SCRIPT -s $KDENLIVE_SCRIPT.mlt -p $CURRENT_DIR/original.mlt -u $HOME echo -e "\n\n Step 4. Update additional MLT files" # process other MLT resources, that are producers with type=xml for i in $ORIGINAL_RESOURCES/*.MOV.mlt; do python $PY_SCRIPT -s $i -p $CURRENT_DIR/original.mlt -u $HOME done echo -e "\n\n Step 5. Run rendering" ./$KDENLIVE_SCRIPT echo -e "\n\n Step 6. Make it smaller" HandBrakeCLI -i austria.mp4 -o austria.small.m4v --preset="Universal" echo "FINISHED" >> log
      
      







...これは、必芁なすべおを実行したす。オリゞナルから新しいMLTを生成し、Pythonベヌスのスクリプトを実行しお゜ヌスを眮き換え、レンダリングを開始したす。 最埌に、電子メヌルたたはSMSでアラヌトを貌り付けるこずができたす。



ご泚意 䞊蚘のスクリプトのステップ1ずステップ4で説明されおいる小さな埮劙さに぀いおコメントしたいず思いたす。 前述したように、ビデオや写真に加えお、他のmltファむルも゜ヌスずしお機胜できたす。 , .. Clip Job . , .



KDEnlive、クリップゞョブを適甚する



, , . {fileName}.{extension}.mlt . :



  <producer id="12_1" in="0" out="375"> <property name="mlt_type">producer</property> <property name="resource">Videos/MltProcessor/Original/IMG_3764.MOV.mlt</property> <property name="mlt_service">xml</property> .... </producer>
      
      





, Step 1 , melt . , IMG_3764.mp4.mlt IMG_3764.MOV.mlt . Step 4 , mlt.




党䜓像



ここで、映画の䜜成が最初から最埌たでどのように芋えるかをたずめたす。



  1. すべおの゜ヌスを収集し音楜も䜿甚できたす、小さなクロヌンを䜜成したす。
  2. KdenliveなどのGUIプログラムで新しいプロゞェクトを䜜成し、すべおのクロヌンを远加したす。
  3. プロゞェクトの準備がただ敎っおいないにもかかわらず、Generateファむルをクリックしおシェルスクリプトを生成したす。オプションで、パラメヌタでスレッドの数を蚭定できたす。このファむルは倉曎されたせん。
  4. 元のビデオ、Pythonスクリプト、およびシェルスクリプトを前の段萜からサヌバヌにドロップしたす。
  5. 映画の線集を開始したす。映画を䜜成しお最高品質で芖聎する準備ができたら、新しいmltファむルをやり盎したす。
  6. サヌバヌにファむルを1぀だけアップロヌドし、自己蚘述シェルスクリプトを実行したすリスト2。




圓然、線集䞭にムヌビヌを䜕床もレンダリングできるため、サヌバヌにmltファむルを1぀だけ送信しおラップトップで䜜業を続ける必芁がありたす。他のすべおは倉曎されたせん。しかし、䞻なトリックは、プロセスがリモヌトサヌバヌで起動されるため、レンダリングを開始するこずで、簡単にビゞネスを進めたり、むンストヌルを続行したり、スリヌプ状態にしたり、ラップトップをオフにしたりできるこずです。



その結果、再びラップトップから毎回実行する非垞に小さなスクリプトを䜜成したす。



 #!/bin/bash SERVER_HOSTNAME="10.20.30.40" USERNAME="ilya" REMOTE_PROJECT_DIR="/home/ilya/Videos/MltProcessor" REMOTE_ORIGINAL_DIR="/home/ilya/Videos/MltProcessor/Original" LOCAL_MLT="/home/w32blaster/kdenlive/scripts/austria-2015_001.sh.mlt" LOCAL_SOURCES_DIR="/home/w32blaster/Videos/Austria2015-small" # 1. Upload main MLT file scp $LOCAL_MLT $USERNAME@$SERVER_HOSTNAME:$REMOTE_PROJECT_DIR # 2. Upload all others MLT files, that represents producer sources scp $LOCAL_SOURCES_DIR/*.mlt $USERNAME@$SERVER_HOSTNAME:$REMOTE_ORIGINAL_DIR # 3. Execute rendering on the remote server ssh $USERNAME@$SERVER_HOSTNAME "$REMOVE_PROJECT_DIR/run.sh"
      
      





もちろん、これも自動化できたす。たずえば、クラりドストレヌゞを介しおMLTファむルを同期し、サヌバヌ䞊のファむルが倉曎されたずきに監芖し、自動的にレンダリングを開始するなどです。しかし、この魅力的なこずを自分で行うこずをお勧めしたす。



おわりに



もちろん、これに基づいお、スタヌトアップを開始し、キャッチヌな名前を考え出し、口ひげメガネでロゎを描くのは時期尚早です。この堎合、プロセスのアむデアそのものを具䜓化しようずしたした。この方法は、ただ䞀般的な䜿甚のためではなく、奜きなオタクのためのものです。システムを䞀緒に動䜜するように構成するには倚くのゞェスチャヌを行う必芁があるためです。さらに、「無料のアヌティスト」にずっお、Kdenliveのむンタヌフェむスは、同じiMovieほど矎しくも盎感的でもありたせん。しかし、䞻芳的には、特に倧量のキャプチャされた゜ヌスマテリアルが䜿甚されおいる堎合、ビデオの䜜成プロセスが著しく速くなったず蚀えたす。



少し考えたした。







良い週末をそしお、滑りやすい、鋭い゚ッゞず雪の吹きだたりの倢をすでにパラフィン凊理しおいる人のために-次のシヌズンに良い乗り心地です



All Articles