yokoyama のすべての投稿

UbuntuでDVDを作る

dvd-slideshowというツールを使うと、旅行などで撮った写真を簡単にスライドショーとしてvobファイルを作ることができそうです。

インストールはsynapticから、dvd-slideshowを検索してインストールするだけです。

関連アプリケーションもインストールされます。

ただし、このツールはコマンドラインで使用するツールなので、設定等はテキストファイルにしないといけないのです。

dir2slideshowというヘルパーアプリケーションを使うと、指定したディレクトリの画像を、指定したエフェクトをつけて

スライドショーにする設定ファイルを作成してくれます。

オプションの指定で、フェードインやクロスフェードなどのエフェクトも指定できます。

$ dir2slideshow -o . -t 10 -n sample /media/photo

すると、sample.txtファイルが作成され、以下のようなテキストが出力されていました。

background:0::black
title:10:sample
fadeout:1
background:1
fadein:1
/media/photo/rimg0004.jpg:10
/media/photo/rimg0005.jpg:10
/media/photo/rimg0006.jpg:10
/media/photo/rimg0007.jpg:10
/media/photo/rimg0008.jpg:10
/media/photo/rimg0009.jpg:10
/media/photo/rimg0010.jpg:10
/media/photo/rimg0011.jpg:10
/media/photo/rimg0012.jpg:10
/media/photo/rimg0013.jpg:10
/media/photo/rimg0014.jpg:10
/media/photo/rimg0015.jpg:10
/media/photo/rimg0016.jpg:10
/media/photo/rimg0017.jpg:10
/media/photo/rimg0018.jpg:10
/media/photo/rimg0019.jpg:10
fadeout:1
background:1

やっと本命の、DVDファイル(.vobファイル)を作成します。

コマンドラインから、dvd-slideshowを呼び出します。

$dvd-slideshow -n sample -o . -a ./vivaldi.mp3 -f sample.txt

-nオプションはタイトル名

-oオプションは出力先ディレクトリ名(出力ファイル名は xxxxx.vobとなります)

-aオプションはBGM

-fオプションはdir2slideshowで作成した設定ファイルです。

その他、背景画像の指定オプションなどがあります。

これでvobファイルが出力されるかと思いきや、BGM関連でエラーが発生し、処理が中断してしまいました。

-aオプションをつけなくても同じエラーでした。

ネットでエラーを調べてみると、libsoxで使用できるファイルフォーマットがデフォルトでは少ないことが原因のようです。

[ubuntu] dvdslideshow problem

ここでかかれている解決方法を実施しました。

sudo apt-get install libsox-fmt-all
sudo sed -i ‘s/-ab 192/-ab 192k/g’ /usr/bin/dvd-slideshow

そして、再度dvd-slideshowコマンドを実行すると、正常にsample.vobファイルと、

チャプター情報が書かれたsample.xmlが作成されました。

vobファイルは正常に再生できたので、後はDVD-Rに書き込むだけです。

pythonで画像表示

pythonのGUIモジュールであるpygtkを使うと、簡単にウィンドウアプリケーションが作成できます。

しかもRADツールであるgladeインターフェース・デザイナを使えば、GUIの構成もサクサクです。

ということで、指定した画像を表示するアプリケーションを作ってみます。

環境はpythonとpygtkが動けばOKです。

まずは、pythonのコードです。

simage.pyファイルとして、保存して下さい。

[sourcecode language=”python”]
#! /usr/bin/env python
# -*- coding: UTF-8 -*-

# インポート
import pygtk
pygtk.require("2.0")
import gtk
import gtk.glade

# メインウィンドウクラスの定義
class MainWindow:

# コンストラクタ
def __init__(self):
# gladeファイルから一発でGUIを構築
self.widgets = gtk.glade.XML("simage.glade", "window")

# イベントハンドラの割り当て
self.auto_connects()

# GtkImageをscrolledwindowに追加する
self.image = gtk.Image()
self["scrolledwindow"].add_with_viewport(self.image)

# MainWindowを表示する
self["window"].show_all()

# イベントハンドラの追加(gtk_ではじまるメソッドを登録)
def auto_connects(self):
event_handlers = {}
for (itemname, value) in self.__class__.__dict__.items():
if callable(value) and itemname.startswith(‘gtk_’):
event_handlers[itemname[4:]] = getattr(self, itemname)
self.widgets.signal_autoconnect(event_handlers)

# 指定されたアイテムが見つからない時に呼び出す(widgetの呼び出しを簡単にする)
def __getitem__(self, key):
return self.widgets.get_widget(key)

# ウィンドウの「閉じる」ボタンを押したときのイベントハンドラ
def gtk_on_window_delete_event(self, widget, event=None):
gtk.main_quit()

# メニューの「終了」を選んだときのイベントハンドラ
def gtk_on_quit_menu_item_activate(self, widget):
gtk.main_quit()

# メニューの「開く」を選んだときのイベントハンドラ
def gtk_on_open_menu_item_activate(self, widget):
dlg = gtk.FileChooserDialog(
"画像を開く",
None,
gtk.FILE_CHOOSER_ACTION_OPEN,
(
gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN,gtk.RESPONSE_OK
)
)
dlg.set_default_response(gtk.RESPONSE_OK)

# 画像ファイルのフィルタを作る
filter = gtk.FileFilter()
filter.set_name("Images")
filter.add_mime_type("image/jpeg")
filter.add_mime_type("image/gif")
filter.add_mime_type("image/png")
filter.add_pattern("*.jpg")
filter.add_pattern("*.gif")
filter.add_pattern("*.png")
dlg.add_filter(filter)

# すべてのファイルのフィルタも作る
filter = gtk.FileFilter()
filter.set_name("All files")
filter.add_pattern("*")
dlg.add_filter(filter)

# ダイアログの表示
res = dlg.run()

# 「OK」ボタンを押したら、画像ファイルを開く
if res == gtk.RESPONSE_OK:
self.open_image(dlg.get_filename())

# ダイアログの破棄
dlg.destroy()

# 指定された画像を開く
def open_image( self, filename ):
self.image.set_from_file(filename)

# スタートアップ
if __name__ == "__main__":
window = MainWindow()
gtk.main()
[/sourcecode]

続いて、gladeファイルです。

simage.gladeファイルとして保存して下さい。

[sourcecode language=”xml”]
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!–Generated with glade3 3.4.5 on Thu Apr 30 17:55:07 2009 –>
<glade-interface>
<widget class="GtkWindow" id="window">
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="title" translatable="yes">Simple Image Viewer</property>
<property name="default_width">350</property>
<property name="default_height">350</property>
<signal name="destroy" handler="on_window_destroy"/>
<signal name="delete_event" handler="on_window_delete_event"/>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<widget class="GtkMenuBar" id="menubar1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<widget class="GtkMenuItem" id="menuitem1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">ファイル(_F)</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menu1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<widget class="GtkImageMenuItem" id="open_menu_item">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">開く(_O)</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_open_menu_item_activate"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image2">
<property name="stock">gtk-open</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="quit_menu_item">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">終了(_Q)</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_quit_menu_item_activate"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image5">
<property name="stock">gtk-quit</property>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="border_width">1</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkStatusbar" id="statusbar">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="spacing">2</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>
[/sourcecode]

このgladeファイルは、gladeインターフェース・デザイナver3で作成しましたので、そのまま読み込むことができます。

よって、このXMLファイルは理解していなくても、gtkモジュールが勝手に解釈してくれます。

pythonコードをみると、22行目でGtkImageをロードしています。

gladeインターフェース・デザイナにもGtkImageはありますので、そこで設置しておけば良いはず。

しかし、設置して実行してみると、gladeの初期化(16行目)で警告が表示され、
ウィンドウのスクロールが正常に動作しませんでした。

./simage.py:16: GtkWarning: gtk_scrolled_window_add(): cannot add non scrollable widget use gtk_scrolled_window_add_with_viewport() instead
self.widgets = gtk.glade.XML(“simage.glade”, “window”)

とりあえず、プログラムでGtkImageを設置すると大丈夫です。

ということで、100行も書かずに画像ビューワが完成です。